HtmlUnit中AJAX执行的问题

一、概述

    HtmlUnit,不多介绍,Java中的开源无UI“浏览器”。在一些小的爬虫项目中想要爬取数据,现在很多网站使用大量ajax,普通爬虫无法获取js生成的内容。HtmlUnit对JS、AJAX支持比较好,可以得到最终呈现的HTML源代码数据。


二、方案

   1、第一步,我们需要配置WebClient,如下代码

WebClient webClient=new WebClient(BrowserVersion.FIREFOX_17);//设置浏览器的User-Agent
webClient.setJavaScriptTimeout(10000);//设置JS执行的超时时间
webClient.getOptions().setThrowExceptionOnScriptError(false);//当JS执行出错的时候是否抛出异常
webClient.getOptions().setThrowExceptionOnFailingStatusCode(false);//当HTTP的状态非200时是否抛出异常
webClient.getOptions().setTimeout(30000);//设置“浏览器”的请求超时时间
ebClient.getOptions().setCssEnabled(false);//是否启用CSS
webClient.getOptions().setJavaScriptEnabled(true); //很重要,启用JS
webClient.waitForBackgroundJavaScript(30000);//设置JS后台等待执行时间
webClient.setAjaxController(new NicelyResynchronizingAjaxController());//很重要,设置支持AJAX

 当我们设置后以上选项后,依然无法得到AJAX执行完成后HTML页面呈现的数据。针对此,官网FQA给出了回答:

Nothing happens when using HtmlUnit with AJAX, although page works correctly in browsers. What's wrong?

The main thread using HtmlUnit may be finishing execution before allowing background threads to run. You have a couple of options:

webClient.setAjaxController(new NicelyResynchronizingAjaxController()); will tell your WebClient instance to re-synchronize asynchronous XHR.

webClient.waitForBackgroundJavaScript(10000); or webClient.waitForBackgroundJavaScriptStartingBefore(10000); just after getting the page and before manipulating it.

Explicitly wait for a condition that is expected be fulfilled when your JavaScript runs, e.g.

       //try 20 times to wait .5 second each for filling the page.
        for (int i = 0; i < 20; i++) {
            if (condition_to_happen_after_js_execution) {
                break;
            }
            synchronized (page) {
                page.wait(500);
            }
        }


三、示例代码

HtmlPage resultPage =  (HtmlPage)page;
HtmlElement resultData = resultPage.getBody().getElementById("hdivResultPanel");
List<HtmlElement> columns = resultData.getElementsByAttribute("div", "class", "avt_column");
//try 20 times to wait .5 second each for filling the page.
for (int i = 0; i < 20; i++) {
     if (columns.size()>0) {
           logger.info("等待ajax执行完毕");
           break;
     }
      synchronized (resultPage) {
           page.wait(500);
      }
}		
//解析来,可以针对resultPage进行数据解析工作……




你可能感兴趣的:(js,Ajax,爬虫,htmlunit)