使用HTMLUnit抓取Google Shopping链接时href失真问题求解
我用HTMLUnit从Google Shopping结果里提取锚点元素的href属性,代码如下:
List<HtmlElement> urls = page.getByXPath("//a[contains(@class,'Lq5OHe eaGTj translate-content')]");
但提取到的链接出现失真:
- 浏览器中看到的有效链接:
https://www.universitysupplystore.com/shop_product_detail.asp?catalog_group_id=MjE&catalog_group_name=VGlkZSBUZWNo&catalog_id=599&catalog_name=TWFjQm9vaw&pf_id=202680&product_name=MTMtSW5jaCBNYWNib29rIEFpciBBcHBsZSBNMiBDaGlwIFdpdGggOC1Db3JlIENwdSBBbmQgOC1Db3JlIEdwdS84R2IgVW5pZmllZCBNZW1vcnk&type=1&target=shop_product_list.asp
- HTMLUnit提取到的无效链接(带编码和Google追踪参数):
https://www.universitysupplystore.com/shop_product_detail.asp%3Fcatalog_group_id%3DMjE%26catalog_group_name%3DVGlkZSBUZWNo%26catalog_id%3D599%26catalog_name%3DTWFjQm9vaw%26pf_id%3D202680%26product_name%3DMTMtSW5jaCBNYWNib29rIEFpciBBcHBsZSBNMiBDaGlwIFdpdGggOC1Db3JlIENwdSBBbmQgOC1Db3JlIEdwdS84R2IgVW5pZmllZCBNZW1vcnk%26type%3D1%26target%3Dshop_product_list.asp&rct=j&q=&esrc=s&sa=U&ved=0ahUKEwjtzMqfoLD5AhVIBUQIHXbUBmoQ2SkIww4&usg=AOvVaw2Bom-oAHHYL7PLWixwFHes
观察到链接里的?、&被编码成%3F、%26,还额外带了Google的追踪参数,导致无法正常访问,请问怎么提取原始有效链接?
1. 解码URL编码部分
Google Shopping的这类链接经过了转义编码,先用URLDecoder解码处理特殊字符:
import java.net.URLDecoder; import java.nio.charset.StandardCharsets; for (HtmlElement element : urls) { String rawHref = element.getAttribute("href"); // 解码处理%3F、%26这类编码字符 String decodedHref = URLDecoder.decode(rawHref, StandardCharsets.UTF_8.name()); }
2. 剥离Google追踪参数
解码后链接末尾会带有&rct=j&q=&esrc=s...这类追踪参数,直接截断即可:
for (HtmlElement element : urls) { String rawHref = element.getAttribute("href"); String decodedHref = URLDecoder.decode(rawHref, StandardCharsets.UTF_8.name()); // 截断追踪参数,保留核心链接 if (decodedHref.contains("&rct=")) { decodedHref = decodedHref.split("&rct=")[0]; } // 此时decodedHref就是可正常访问的原始链接 System.out.println(decodedHref); }
3. 用HtmlAnchor的内置方法获取真实URL
如果将元素强转为HtmlAnchor,可以直接调用HTMLUnit的内置方法获取解析后的真实URL,自动处理编码逻辑:
import com.gargoylesoftware.htmlunit.html.HtmlAnchor; List<HtmlAnchor> anchors = page.getByXPath("//a[contains(@class,'Lq5OHe eaGTj translate-content')]"); for (HtmlAnchor anchor : anchors) { String realUrl = anchor.getPage().getUrl().toString(); // 同样剥离追踪参数 if (realUrl.contains("&rct=")) { realUrl = realUrl.split("&rct=")[0]; } System.out.println(realUrl); }
内容的提问来源于stack exchange,提问作者Cassie Nguyen

