ajax抓取网页内容(越来越多的网站将Ajax用于精美的用户体验,简化它)
优采云 发布时间: 2022-01-23 23:13ajax抓取网页内容(越来越多的网站将Ajax用于精美的用户体验,简化它)
今天,越来越多的网站使用 Ajax 来获得漂亮的用户体验、动态网页以及许多其他好的理由。
搜索繁琐的 Ajax网站 可能有点棘手和痛苦,我们将看到一些技巧来简化它。
先决条件
在开始之前,请阅读我写的前几篇文章文章,了解如何设置您的 Java 环境并基本了解如何开始使用 HtmlUnit Java 进行网络爬取和处理身份验证。
看完这篇文章,你应该对网络爬虫更加熟悉了。
设置
我们将了解在 Java 中抓取 Ajax 的第一种方法网站 是将 PhantomJS 与 Selenium 和 GhostDriver 结合使用。
PhantomJS 是一个基于 WebKit 的无头 Web 浏览器(用于 Chrome 和 Safari)。它非常快,并且可以像普通的网络浏览器一样呈现 Dom。
com.github.detro
phantomjsdriver
1.2.0
还有这个:
org.seleniumhq.selenium
selenium-java
2.53.1
PhantomJS 和 Selenium
我们现在将使用 Selenium 和 GhostDriver “试点” PhantomJS。
我们将要看到的示例是新闻网站上的一个简单的“查看更多”按钮,它执行 ajax 调用以加载更多新闻。
所以你可能认为打开 PhantomJS 来点击一个简单的按钮是浪费时间和大量时间?当然!
新闻网站是:简而言之
与往常一样,我们必须打开 Chrome 开发工具或您最喜欢的检查器,以查看如何选择“加载更多”按钮并单击它。
现在让我们看一些代码:
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 调用所需的时间,scraper 可以运行得更快。
还有其他方法可以解决这个问题:
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 调用次数)
如果我们知道 Ajax 调用应该渲染哪些 DOM 元素,我们可以在 WebDriverWait 条件中使用该 id/class/xpath:
wait . until ( ExpectedConditions . elementToBeClickable ( By . xpath ( xpathExpression )))
结论
所以,我们已经了解了如何在 Java 中使用 PhantomJS。
我给出的例子很简单,模拟一个请求很容易。
但有时当您有几十个 Ajax 调用,并执行大量 Javascript 以正确呈现页面时,很难抓取您需要的数据,PhantomJS/Selenium 将您保存在这里 :)
下一次,我们将通过分析 AJAX 调用并自己发出请求来了解如何做到这一点。
与往常一样,您可以在我的 Github 存储库中找到所有代码
*敏*感*词*渲染 JS 真的很困难而且很昂贵。这就是我们构建 ScrapingBee 的原因,它是一个网络抓取 API,可以为您处理这些问题。
它还会使用代理和验证码,不要犹豫,前 1000 个 API 调用即将到来。
发件人: