请看下图。红色箭头之前的元素已加载,但其后的 4 个元素由于某种原因未加载。
我选择这些元素的方式是,
doc = Jsoup.connect(url).header("Accept-Encoding", "gzip, deflate").userAgent("Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2228.0 Safari/537.36").maxBodySize(0).timeout(600000).get();
Elements detailsBuyBoxContainer = doc.select("li[class^=product-tile]");
System.out.println(detailsBuyBoxContainer.size());
还尝试使用下面的选择
/*Elements detailsBuyBoxContainer = doc.getElementsByAttributeValueContaining("class",
"details-buy-box-container");*/
打印的尺寸应该是 24 而不是 20
最佳答案
该列表部分由客户端 JavaScript(即 AJAX 调用)填充。 JSoup 不运行 Javascript,也不是浏览器,因此您尝试的简单方法行不通。
我看到两种解决方案:
A) 使用 Selenium webdriver,它是一个真正的浏览器,可以很好地加载 AJAX 内容。
B) 自己识别AJAX调用并使用JSoup直接调用Api url。解释这一点通常并不难,尽管您可能必须使用不同的抓取技术,例如解释 JSON 而不是 HTML。
附录
我进一步研究了 tesco 网站,他们似乎使用了一种有点有趣的方法来发送包含 HTML 的 JSON 响应。我想这可以节省客户端上的一些 JavaScript 工作,但这仍然有点奇怪。那好吧。这是我使用浏览器网络选项卡捕获的调用。当您向下滚动列表时,将进行 Ajax 调用 http://www.tesco.com/direct/blocks/catalog/productlisting/infiniteBrowse.jsp?&view=grid&catId=4294967294+4294814304&sortBy=&searchquery=espresso+机器&offset=20&lazyload=true
看来您需要增加偏移参数才能获得更多结果。此类调用的内容是一个包含两个属性的 JSON 对象:“产品”和“变体”。 products 属性似乎包含 html。
所以一步一步:
1) 使用 Jsoup(或者例如 Apache HttpClient)获取 Ajax 调用的原始内容:
Connection con = Jsoup.connect("http://www.tesco.com/direct/blocks/catalog/productlisting/infiniteBrowse.jsp?&view=grid&catId=4294967294+4294814304&sortBy=&searchquery=espresso+machine&offset=20&lazyload=true")
.ignoreContentType(true);
Response res = con.execute();
String rawJSON = res.body();
2) 根据您的喜好使用库解析 JSON。我通常使用Json-Simple
JSONObject o = (JSONObject) JSONValue.parse(html);
String html = (String) o.get("products");
请注意,JSON-Simple 易于使用,但不使用泛型。您可能还想研究 Jackson 的 Gson。
3)使用 JSoup 解析 html:
Document doc = Jsoup.parse(html);
关于java - Jsoup select 未获取所有元素,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32022167/