抓取ajax动态网页java(越来越多的网站将Ajax用于精美的用户体验,简化它)
优采云 发布时间: 2021-10-14 11:26抓取ajax动态网页java(越来越多的网站将Ajax用于精美的用户体验,简化它)
如今,越来越多的 网站 使用 Ajax 来获得精美的用户体验、动态网页和许多其他很好的理由。
搜索繁琐的 Ajax网站 可能既棘手又痛苦,我们将看到一些简化它的技巧。
先决条件
开始之前请先阅读我写的前几篇文章,了解如何搭建Java环境,对HtmlUnit Java for Web爬取和认证有一个基本的了解。
阅读本文后,您应该对网页抓取更加熟悉。
设置
我们将看到的第一种使用 Java 抓取 Ajax 的方法网站 是将 PhantomJS 与 Selenium 和 GhostDriver 结合使用。
PhantomJS 是一个基于 WebKit(在 Chrome 和 Safari 中使用)的无头 Web 浏览器。它非常快,可以像普通 Web 浏览器一样渲染 Dom。
com.github.detro
phantomjsdriver
1.2.0
还有这个:
org.seleniumhq.selenium
selenium-java
2.53.1
PhantomJS 和 Selenium
现在,我们将使用 Selenium 和 GhostDriver 来“试用”PhantomJS。
我们将要看到的示例是新闻网站上的一个简单的“查看更多”按钮,它执行 ajax 调用以加载更多新闻。
所以你可能会认为打开 PhantomJS 点击一个简单的按钮是浪费时间和大量时间?当然!
新闻网站是:简而言之
与往常一样,我们必须打开 Chrome Dev 工具或您最喜欢的检查器才能查看如何选择“加载更多”按钮并点击它。
现在让我们看一些代码:
private static String USER_AGENT = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.116 Safari/537.36" ;
private static DesiredCapabilities desiredCaps ;
private static WebDriver driver ;
public static void initPhantomJS (){
desiredCaps = new DesiredCapabilities ();
desiredCaps . setJavascriptEnabled ( true );
desiredCaps . setCapability ( "takesScreenshot" , false );
desiredCaps . setCapability ( PhantomJSDriverService . PHANTOMJS_EXECUTABLE_PATH_PROPERTY , "/usr/local/bin/phantomjs" );
desiredCaps . setCapability ( PhantomJSDriverService . PHANTOMJS_PAGE_CUSTOMHEADERS_PREFIX + "User-Agent" , USER_AGENT );
ArrayList cliArgsCap = new ArrayList ();
cliArgsCap . add ( "--web-security=false" );
cliArgsCap . add ( "--ssl-protocol=any" );
cliArgsCap . add ( "--ignore-ssl-errors=true" );
cliArgsCap . add ( "--webdriver-loglevel=ERROR" );
desiredCaps . setCapability ( PhantomJSDriverService . PHANTOMJS_CLI_ARGS , cliArgsCap );
driver = new PhantomJSDriver ( desiredCaps );
driver . manage (). window (). setSize ( new Dimension ( 1920 , 1080 ));
}
设置phantomJs和Selenium有很多代码!
建议您阅读文档以了解可以传递给 PhantomJS 的许多参数。
请注意,您必须将 /usr/local/bin/phantomjs 替换为您自己的 phantomJs 可执行路径
然后在main方法中:
System . setProperty ( "phantomjs.page.settings.userAgent" , USER_AGENT );
String baseUrl = "https://www.inshorts.com/en/read" ;
initPhantomJS ();
driver . get ( baseUrl ) ;
int nbArticlesBefore = driver . findElements ( By . xpath ( "//div[@class='card-stack']/div" )). size ();
driver . findElement ( By . id ( "load-more-btn" )). click ();
// We wait for the ajax call to fire and to load the response into the page
Thread . sleep ( 800 );
int nbArticlesAfter = driver . findElements ( By . xpath ( "//div[@class='card-stack']/div" )). size ();
System . out . println ( String . format ( "Initial articles : %s Articles after clicking : %s" , nbArticlesBefore , nbArticlesAfter ));
这里,我们调用 initPhantomJs() 方法来设置所有内容,然后选择带有其 ID 的按钮并单击它。
代码的另一部分计算页面上已经存在的文章的数量并打印出来以显示我们加载的内容。
我们也可以使用driver.getPageSource()来打印整个dom并在真实浏览器中打开查看点击前后的差异。
我建议你看看 Selenium Webdriver 文档,有很多很酷的方法来操作 DOM。
我使用了 Thread.sleep(800) 的脏解决方案来等待 Ajax 调用完成。
它很脏,因为它是一个任意数字。如果我们只等待执行那个 ajax 调用所需的时间,那么爬虫可以运行得更快。
还有其他方法可以解决这个问题:
public static void waitForAjax ( WebDriver driver ) {
new WebDriverWait ( driver , 180 ). until ( new ExpectedCondition () {
public Boolean apply ( WebDriver driver ) {
JavascriptExecutor js = ( JavascriptExecutor ) driver ;
return ( Boolean ) js . executeScript ( "return jQuery.active == 0" );
}
});
}
如果您查看单击按钮时正在执行的函数,您会看到它使用的是 jQuery:
这段代码会一直等到变量jQuery.active等于0(这个好像是jQuery的内部变量,用来统计正在进行的ajax调用次数)
如果我们知道哪些DOM元素应该被Ajax调用渲染,我们可以使用WebDriverWait条件下的id/class/xpath:
wait . until ( ExpectedConditions . elementToBeClickable ( By . xpath ( xpathExpression )))
结论
所以,我们已经学会了如何在 Java 中使用 PhantomJS。
我举的例子很简单,很容易模拟一个请求。
但有时,当您有几十个 Ajax 调用并执行大量 Javascript 以正确呈现页面时,很难抓取所需的数据。 PhantomJS/Selenium 为您提供了帮助 :)
下一次,我们将通过分析 AJAX 调用和自己发出请求来了解如何做到这一点。
一如既往,您可以在我的 Github 存储库中找到所有代码
*敏*感*词*渲染JS确实是非常困难和昂贵的。这正是我们构建 ScrapingBee 的原因。 ScrapingBee 是一个网页抓取 API,可以为您解决这个问题。
它还会使用代理和验证码,不要犹豫,前 1000 个 API 调用即将到来。
来自: