htmlunit抓取动态网页(Java爬取博客阅读文章最多)
优采云 发布时间: 2021-10-11 18:12htmlunit抓取动态网页(Java爬取博客阅读文章最多)
更新,这很尴尬。这个文章博客阅读量最多文章,但也被最讨厌。
爬行思路:
所谓动态,就是可以通过请求后台动态改变对应的html页面,一开始页面并不是全部显示出来的。
大多数操作都是通过请求来完成的,一个请求,一个返回。在大多数网页中,请求往往被开发者隐藏在 js 代码中。
因此,爬取动态网页的思路转化为寻找对应的js代码,并执行对应的js代码,从而通过java代码动态改变页面。
而当页面能够正确显示时,我们就可以像抓取静态网页一样抓取数据了!
首先可以使用htmlunit来模拟鼠标点击事件,实现起来很简单:
/**
* 通过htmlunit来获得一些搜狗的网址。
* 通过模拟鼠标点击事件来实现
* @param key
* @return
* @throws Exception
*/
public String getNextUrl(String key){
String page = new String();
try {
WebClient webClient = new WebClient();
webClient.getOptions().setCssEnabled(false);
webClient.getOptions().setJavaScriptEnabled(false);
//去拿网页
HtmlPage htmlPage = webClient.getPage("http://pic.sogou.com/");
//得到表单
HtmlForm form = htmlPage.getFormByName("searchForm");
//得到提交按钮
HtmlSubmitInput button = form.getInputByValue("搜狗搜索");
//得到输入框
HtmlTextInput textField = form.getInputByName("query");
//输入内容
textField.setValueAttribute(key);
//点一下按钮
HtmlPage nextPage = button.click();
String str = nextPage.toString();
page = cutString(str);
webClient.close();
} catch (Exception e) {
e.printStackTrace();
}
return page;
}
如上图,我通过java代码将关键字填入搜索我的,然后通过getInputByValue方法获取按钮控件,最后直接button.click(),
也就是说可以模拟点击,点击后返回的http请求可以解析成htmlpage。
这个功能其实非常强大。例如,您可以使用该功能来模拟抢票,或者使用点击事件和搜索相关知识将整个系统下线并保存在 html 中。
下一步就是使用强大的 htmlunit 来执行 js 代码了。
先写一个简单的jsp页面:
Insert title here
原数字
function change(value) {
document.getElementById("test").innerHTML = value;
return "hello htmlUnit";
}
从上面可以看出,jsp页面很简单,只是一个函数变化,用来调用htmlUnit。
接下来是一个使用 htmlunit 的类。这个类支持 JavaScript 解释器,
然后将自己编写的JavaScript代码嵌入到页面中执行,执行后得到返回结果返回页面。
package com.blog.anla;
import com.gargoylesoftware.htmlunit.ScriptResult;
import com.gargoylesoftware.htmlunit.WebClient;
import com.gargoylesoftware.htmlunit.html.HtmlPage;
public class TestMyOwnPage {
private void action() {
WebClient webClient = new WebClient();
try {
webClient.getOptions().setCssEnabled(false);
webClient.getOptions().setJavaScriptEnabled(true); // 设置支持JavaScript。
// 去拿网页
HtmlPage htmlPage = webClient
.getPage("http://localhost:8989/testHtmlScrop/index.jsp");
String s = "更改后的数字";
ScriptResult t = htmlPage.executeJavaScript("change(\"" + s
+ "\");", "injected script", 500);
// 这里是在500行插入这一小行JavaScript代码段,因为如果在默认的1行,那不会有结果
// 因为js是顺序执行的,当你执行第一行js代码时,可能还没有渲染body里面的标签。
HtmlPage myPage = (HtmlPage) t.getNewPage();
String nextPage = myPage.asXml().toString();
String nextPage2 = myPage.asText().toString();
} catch (Exception e) {
e.printStackTrace();
} finally {
webClient.close();
}
}
public static void main(String[] args) {
TestMyOwnPage tmop = new TestMyOwnPage();
tmop.action();
}
}
t.getNewPage() 中有两个属性,一个是
javaScriptResult:执行代码后返回的结果,如果有(如我上面写的,返回hello htmlunit),如果没有(返回Undefined)。
newPage_:执行这段代码后返回的整个页面。
结果如图所示:
这段代码执行的最终结果如下:
asXml():将整个页面的html代码返回给我们:
而asText()只返回页面上可以显示的值,即head标签和label标签:
这种执行思路也可以动态的执行对应的js代码,从而抓取到需要的数据。
-------------------------------------------------- -------------------------------------- 2017 年 7 月更新------- ------------------------------------------------- - ----------------------------------------------
这两天一直在研究一个关于网络爬虫的系统
但是第一次爬的时候就发现了这个问题,js的动态页面爬不下来。
网上找了很多方法,google也问了,主要是指htmlunit,下面是核心代码,
使用htmlunit的主要目的是模拟浏览器操作,因为有些链接点击无法通过src直接获取url,通常使用JavaScript
简单拼接后的URL,这样一来,相比之下,直接用htmlunit模拟浏览器点击就简单多了。
WebClient webClient = new WebClient();
webClient.getOptions().setJavaScriptEnabled(true); //启用JS解释器,默认为true
webClient.getOptions().setCssEnabled(false); //禁用css支持
webClient.getOptions().setThrowExceptionOnScriptError(false); //js运行错误时,是否抛出异常
webClient.getOptions().setTimeout(20000);
HtmlPage page = wc.getPage("http://www.hao123.com");
//我认为这个最重要
String pageXml = page.asXml(); //以xml的形式获取响应文本
/**jsoup解析文档*/
Document doc = Jsoup.parse(pageXml, "http://cq.qq.com");
这个时候,就可以得到jsoup中的document对象了,接下来就好写了,就像爬普通静态网页一样了。
不过,webclient解析是还是会出现一些问题,js的问题,
主要是由于目标url的js写的有些问题,但在实际的浏览器中却会忽略,eclipse中会报异常。
今天看到的时候,很多人都踩了。也许他们当时没有认真写博客。如果想找java爬虫项目可以到我的专栏。
图片搜索包括使用 jsoup 抓取图片,以及使用 lire 对图片进行索引和搜索。
给玫瑰手留下余香。有什么问题可以多多讨论哦!