HtmlUnit爬取Ajax动态生成的网页以及自动调用页面javascript函数
HtmlUnit官网的介绍:
HtmlUnit是一款基于Java的没有图形界面的浏览器程序。它模仿HTML document并且提供API让开发人员像是在一个正常的浏览器上操作一样,获取网页内容,填充表单,点击超链接等等。
它非常好的支持JavaScript并且仍在不断改进,同时能够解析非常复杂的AJAX库,通过不同的配置来模拟Chrome、Firefox和IE浏览器。
本文针对一个足彩网站抓取的例子,来熟悉HtmlUnit
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的返回结果做修改
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
报错信息:
警告: 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。这个标记是看不到的,而在流里面有这个标记。
因此可以通过以下代码来截取你需要的内容
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
例如:
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函数的更多相关文章
- HtmlUnit爬取Ajax动态生成的页面内容
HtmlUnit说白了就是一个浏览器,这个浏览器是用Java写的无界面的浏览器,正因为其没有界面,因此执行的速度还是可以滴. HtmlUnit提供了一系列的API,这些API可以干的功能比较多,如表单 ...
- 第三百三十四节,web爬虫讲解2—Scrapy框架爬虫—Scrapy爬取百度新闻,爬取Ajax动态生成的信息
第三百三十四节,web爬虫讲解2—Scrapy框架爬虫—Scrapy爬取百度新闻,爬取Ajax动态生成的信息 crapy爬取百度新闻,爬取Ajax动态生成的信息,抓取百度新闻首页的新闻rul地址 有多 ...
- 十三 web爬虫讲解2—Scrapy框架爬虫—Scrapy爬取百度新闻,爬取Ajax动态生成的信息
crapy爬取百度新闻,爬取Ajax动态生成的信息,抓取百度新闻首页的新闻rul地址 有多网站,当你浏览器访问时看到的信息,在html源文件里却找不到,由得信息还是滚动条滚动到对应的位置后才显示信息, ...
- 爬虫——爬取Ajax动态加载网页
常见的反爬机制及处理方式 1.Headers反爬虫 :Cookie.Referer.User-Agent 解决方案: 通过F12获取headers,传给requests.get()方法 2.IP限制 ...
- Python网络爬虫_爬取Ajax动态加载和翻页时url不变的网页
1 . 什么是 AJAX ? AJAX = 异步 JavaScript 和 XML. AJAX 是一种用于创建快速动态网页的技术. 通过在后台与服务器进行少量数据交换,AJAX 可以使网页实现异步更新 ...
- Jsoup配合 htmlunit 爬取异步加载的网页
加入 jsoup 和 htmlunit 的依赖 <dependency> <groupId>org.jsoup</groupId> <artifactId&g ...
- 如何用webbrowser获取ajax动态生成的网页的源码?
1.步骤一:修改IE内核的版本(这个方法厉害了) public Form1() { InitializeComponent();int BrowserVer, RegVal; // get the i ...
- java抓取动态生成的网页
最近在做项目的时候有一个需求:从网页面抓取数据,要求是首先抓取整个网页的html源码(后期更新要使用到).刚开始一看这个简单,然后就稀里哗啦的敲起了代码(在这之前使用过Hadoop平台的分布式爬虫框架 ...
- 抓取Js动态生成数据且以滚动页面方式分页的网页
代码也可以从我的开源项目HtmlExtractor中获取. 当我们在进行数据抓取的时候,如果目标网站是以Js的方式动态生成数据且以滚动页面的方式进行分页,那么我们该如何抓取呢? 如类似今日头条这样的网 ...
随机推荐
- 【Linux学习】Linux用户管理1—用户查询指令、用户切换
Linux用户管理1-用户查询指令.用户切换 一.用户查询指令 who: 查看当前在线用户情况 -a:显示所有用户的所有信息 -m:显示运行该程序的用户名,和"who am I"的 ...
- HTML学习笔记(一)HTML的一些概念区别
HTML HTML 指超文本标记语言.在 HTML 4 中,有若干的标签和属性是被废弃的,替换成style对应的属性 应该避免使用下面这些标签和属性: 标签 描述 style <center&g ...
- PhpStrom之添加文件夹至左侧目录树
1.打开编辑器,点击工具栏 File,并选择Open (File -> Open) 2.选择需要添加的文件夹路径,点击 OK 3.点击OK后弹出下图窗口(第一个选项:Open in new wi ...
- Shader第十三讲 Alpha混合
http://blog.sina.com.cn/s/blog_471132920101d8z5.html Alpha Blending,中文译作Alpha混合Blending就是控制透明的.处于光栅化 ...
- IT兄弟连 JavaWeb教程 JSP动作指令
JSP动作指令语法 JSP动作指令语法格式如下: <jsp:动作名 属性名1="属性值1" 属性名2="属性值2" ... %> JSP具体动作指令 ...
- builder模式的新学习
builder模式的新学习 静态工厂和构造器有个共同的局限性:他们不能很好的扩展到大量的可选参数.大多数产品在牧歌可选与中都会有非零的值 对于这种类,应该使用哪种构造器或者静态方法来进行编写?程序员一 ...
- sequoiadb sdbexprt 导入工具进阶使用
在做sdb 导入操作时,通过more 查看数据,格式是比较正常的,样例数据如下: CB20160630968101173208|||||_*||BZ|B3412|||||09664.8900| ||| ...
- 第二十一篇 .NET高级技术之使用多线程(三)
1. 单元模式和Windows Forms 单元模式线程是一个自动线程安全机制, 非常贴近于COM——Microsoft的遗留下的组件对象模型.尽管.NET最大地放弃摆脱了遗留下的模型,但很多时候它 ...
- 11-1模拟赛 By cellur925
期望得分:70+100+60 实际得分:70+20+60 \(qwq\). T1:有一个 \(n\) × \(n\) 的 \(01\) 方格, 图图要从中选出一个面积最大的矩形区域, 要求这个矩形区域 ...
- 黑马tomact学习二 tomcat的启动