HtmlUnit官网的介绍:

HtmlUnit是一款基于Java的没有图形界面的浏览器程序。它模仿HTML document并且提供API让开发人员像是在一个正常的浏览器上操作一样,获取网页内容,填充表单,点击超链接等等。

它非常好的支持JavaScript并且仍在不断改进,同时能够解析非常复杂的AJAX库,通过不同的配置来模拟Chrome、Firefox和IE浏览器。

本文针对一个足彩网站抓取的例子,来熟悉HtmlUnit

       WebClient wc = new WebClient(BrowserVersion.FIREFOX_38);  
       wc.getOptions().setJavaScriptEnabled(true); //启用JS解释器,默认为true  
       wc.setJavaScriptTimeout(100000);//设置JS执行的超时时间
       wc.getOptions().setCssEnabled(false); //禁用css支持  
       wc.getOptions().setThrowExceptionOnScriptError(false); //js运行错误时,是否抛出异常  
       wc.getOptions().setTimeout(10000); //设置连接超时时间 ,这里是10S。如果为0,则无限期等待  
       wc.setAjaxController(new NicelyResynchronizingAjaxController());//设置支持AJAX
       wc.setWebConnection(
        new WebConnectionWrapper(wc) {
        public WebResponse getResponse(WebRequest request) throws IOException {
                      ......
                   }
        }
       
        );
       HtmlPage page = wc.getPage("http://XXXX.com/");
       FileWriter fileWriter = new FileWriter("D:\\text.html");
       String str = "";
       //获取页面的XML代码
       str = page.asXml();
       fileWriter.write( str );
       //关闭webclient
       wc.close();
       fileWriter.close();

解决数据乱码问题

该网站数据是由js动态载入,并且js有2种编码:

<script language="javascript" src="XXX.js" charset="gb2312"></script>
<script language="javascript" src="XXX.js" charset="utf-8"></script>

可以通过重写WebConnectionWrapper类的getResponse方法来修改返回值

例如,对bfdata.js的返回结果做修改

wc.setWebConnection(
new WebConnectionWrapper(wc) {
public WebResponse getResponse(WebRequest request) throws IOException {
               WebResponse response = super.getResponse(request);
               if (request.getUrl().toExternalForm().contains("bfdata.js")) {
                   String content = response.getContentAsString("GBK");
                   WebResponseData data = new WebResponseData(content.getBytes("UTF-8"),
                           response.getStatusCode(), response.getStatusMessage(), response.getResponseHeaders());
                   response = new WebResponse(data, request, response.getLoadTime());
               }
               return response;
           }
}

);

解决Content is not allowed in prolog

报错信息:

六月 21, 2016 4:15:06 下午 com.gargoylesoftware.htmlunit.xml.XmlPage <init>
警告: Failed parsing XML document http://XXX/vbsxml/goalBf3.xml?r=0071466496906000: Content is not allowed in prolog.
六月 21, 2016 4:15:06 下午 com.gargoylesoftware.htmlunit.javascript.JavaScriptEngine handleJavaScriptException
信息: Caught script exception
======= EXCEPTION START ========
EcmaError: lineNumber=[41] column=[0] lineSource=[<no source>] name=[TypeError] sourceName=[http://XXX/common2.js] message=[TypeError: Cannot read property "childNodes" from null (http://XXX/common2.js#41)]
com.gargoylesoftware.htmlunit.ScriptException: TypeError: Cannot read property "childNodes" from null (http://XXX/common2.js#41)
    at com.gargoylesoftware.htmlunit.javascript.JavaScriptEngine$HtmlUnitContextAction.run(JavaScriptEngine.java:865)
    at net.sourceforge.htmlunit.corejs.javascript.Context.call(Context.java:628)
    at net.sourceforge.htmlunit.corejs.javascript.ContextFactory.call(ContextFactory.java:513)
    at com.gargoylesoftware.htmlunit.javascript.JavaScriptEngine.execute(JavaScriptEngine.java:747)
    at com.gargoylesoftware.htmlunit.html.HtmlPage.loadExternalJavaScriptFile(HtmlPage.java:1032)
    at com.gargoylesoftware.htmlunit.html.HtmlScript.executeScriptIfNeeded(HtmlScript.java:395)
    at com.gargoylesoftware.htmlunit.html.HtmlScript$3.execute(HtmlScript.java:276)

其中警告信息:Content is not allowed in prolog是导致后面报错的原因,而Content is not allowed in prolog是因为解析内容内包含BOM。这个标记是看不到的,而在流里面有这个标记。

因此可以通过以下代码来截取你需要的内容

wc.setWebConnection(
new WebConnectionWrapper(wc) {
public WebResponse getResponse(WebRequest request) throws IOException {
               WebResponse response = super.getResponse(request);
               if(request.getUrl().toExternalForm().contains("goalBf3.xml")){
                String content = response.getContentAsString("UTF-8");
                     if(null != content && !"".equals(content)){  
                     if(content.indexOf("<") != -1 && content.lastIndexOf(">") != -1 && content.lastIndexOf(">") > content.indexOf("<"))  
                     content = content.substring(content.indexOf("<"), content.lastIndexOf(">") + 1);  
                     }

WebResponseData data = new WebResponseData(content.getBytes("UTF-8"),
                                response.getStatusCode(), response.getStatusMessage(), response.getResponseHeaders());
                        response = new WebResponse(data, request, response.getLoadTime());
               }
               return response;
           }
}

);

调用页面javascript函数

该网站有些数据是通过鼠标悬停来获得数据

我们可以通过page.executeJavaScript来执行js

例如:

HtmlPage page = wc.getPage("http://xxx.com/");
wc.waitForBackgroundJavaScript(30 * 1000); /* will wait JavaScript to execute up to 30s */
ScriptResult result = page.executeJavaScript("document.getElementById('pk_1248827').onmouseover(window.event)");
HtmlPage jspage = (HtmlPage) result.getNewPage(); 

HtmlUnit爬取Ajax动态生成的网页以及自动调用页面javascript函数的更多相关文章

  1. HtmlUnit爬取Ajax动态生成的页面内容

    HtmlUnit说白了就是一个浏览器,这个浏览器是用Java写的无界面的浏览器,正因为其没有界面,因此执行的速度还是可以滴. HtmlUnit提供了一系列的API,这些API可以干的功能比较多,如表单 ...

  2. 第三百三十四节,web爬虫讲解2—Scrapy框架爬虫—Scrapy爬取百度新闻,爬取Ajax动态生成的信息

    第三百三十四节,web爬虫讲解2—Scrapy框架爬虫—Scrapy爬取百度新闻,爬取Ajax动态生成的信息 crapy爬取百度新闻,爬取Ajax动态生成的信息,抓取百度新闻首页的新闻rul地址 有多 ...

  3. 十三 web爬虫讲解2—Scrapy框架爬虫—Scrapy爬取百度新闻,爬取Ajax动态生成的信息

    crapy爬取百度新闻,爬取Ajax动态生成的信息,抓取百度新闻首页的新闻rul地址 有多网站,当你浏览器访问时看到的信息,在html源文件里却找不到,由得信息还是滚动条滚动到对应的位置后才显示信息, ...

  4. 爬虫——爬取Ajax动态加载网页

    常见的反爬机制及处理方式 1.Headers反爬虫 :Cookie.Referer.User-Agent 解决方案: 通过F12获取headers,传给requests.get()方法 2.IP限制 ...

  5. Python网络爬虫_爬取Ajax动态加载和翻页时url不变的网页

    1 . 什么是 AJAX ? AJAX = 异步 JavaScript 和 XML. AJAX 是一种用于创建快速动态网页的技术. 通过在后台与服务器进行少量数据交换,AJAX 可以使网页实现异步更新 ...

  6. Jsoup配合 htmlunit 爬取异步加载的网页

    加入 jsoup 和 htmlunit 的依赖 <dependency> <groupId>org.jsoup</groupId> <artifactId&g ...

  7. 如何用webbrowser获取ajax动态生成的网页的源码?

    1.步骤一:修改IE内核的版本(这个方法厉害了) public Form1() { InitializeComponent();int BrowserVer, RegVal; // get the i ...

  8. java抓取动态生成的网页

    最近在做项目的时候有一个需求:从网页面抓取数据,要求是首先抓取整个网页的html源码(后期更新要使用到).刚开始一看这个简单,然后就稀里哗啦的敲起了代码(在这之前使用过Hadoop平台的分布式爬虫框架 ...

  9. 抓取Js动态生成数据且以滚动页面方式分页的网页

    代码也可以从我的开源项目HtmlExtractor中获取. 当我们在进行数据抓取的时候,如果目标网站是以Js的方式动态生成数据且以滚动页面的方式进行分页,那么我们该如何抓取呢? 如类似今日头条这样的网 ...

随机推荐

  1. 【Data Structure & Algorithm】在排序数组中查找和为定值的两个数

    在排序数组中查找和为定值的两个数 题目:输入一个已经按升序排序过的数组和一个数字,在数组中查找两个数,使得它们的和正好是输入的那个数字,要求时间复杂度是O(n).如果有多对数字的和等于输入的数字,输出 ...

  2. 20个Flutter实例视频教程-第10节: 一个不简单的搜索条-1

    20个Flutter实例视频教程-第10节: 一个不简单的搜索条-1 视频地址: https://www.bilibili.com/video/av39709290/?p=10 博客地址: https ...

  3. E20180615-hm

    fraction  n. [数] 分数; 一小部分,些微; 不相连的一块,片段; [化] 分馏; infinity n. <数>无穷大; 无限的时间或空间; product n. 产品; ...

  4. Sql Server2008R2与IDEA的连接

    数据库的连接笔者搞了一天,参阅了众多连接方案,大部分都是Eclipse和My sql,笔者一遍一遍的调试,终于皇天不负有心人,成绩先摆出来 为了让更多的新手能少走弯路,话不多说,上干货 首先,我们需要 ...

  5. SpiderMonkey 入门学习(一)

    spidermonkey 源码下载:http://ftp.mozilla.org/pub/mozilla.org/js/ 测试系统 Ubuntu 12.04, js 1.7.0, js 解压在/opt ...

  6. 测试 | 单元测试工具 | JUnit

    http://junit.sourceforge.net/javadoc/org/junit/Assert.html 使用: 新建测试类: 在预测试的类上点击右键--->NEW--->Ju ...

  7. 最短路之SPFA(单源)HDU 2544

    #include <iostream> #include <queue> #include <algorithm> #define MAXLEN 1005 #def ...

  8. BZOJ1053(数学结论进行剪枝搜索)

    Description 对于任何正整数x,其约数的个数记作g(x).例如g(1)=1.g(6)=4.如果某个正整数x满足:g(x)>g(i) 0<i<x,则称x为反质数.例如,整数1 ...

  9. python入门之实例-用户登录、注册

    用户密码存储文件db(其中用户和密码之间用$符合隔开): admin$123456 root$sdfk9f24 chy$654321 代码如下: def login(username,password ...

  10. [在读]JavaScript异步编程:设计快速响应的网络应用

    很棒的一本,就如书名所示,主要讲js异步的一些东西,比如定时器.Jquery的promise和deffered,node...看了一小半.推荐哦~~