htmlunit是一款java的项目,它是开源的,它是一个没有界面的浏览器可以模拟浏览器的任何行为,比如点击事件,页码跳转,复杂的ajax加载的数据等,如果想使用java进行爬虫,HTMLunit绝对是你的不二之选,下面我会介绍如何使用HTMLunit来爬取一个网站的数据。HTMLunit官网,官网上有帮助文档,都是英文的。
建议:在爬取网站的数据时,最好知道一个网页的结构布局才方便你解析一个网站,爬取数据。
一、首先我们要去官网下载htmlunit,http://htmlunit.sourceforge.net/。
二、用eclipse或者myeclipse新建一个项目,新建一个lib文件夹,将需要的jar放入lib中,并在项目中配置引用lib。
三、
//新建一个浏览器对象,设置模拟使用CHROME浏览器的内核
WebClient webClient = new WebClient(BrowserVersion.CHROME)
//设置webClient的相关参数
//设置是否加载脚本
webClient.getOptions().setJavaScriptEnabled(true);
//设置是否在css样式,建议设置为false可以提高爬取的速度
webClient.getOptions().setCssEnabled(false);
//设置ajax的相关参数
webClient.setAjaxController(new NicelyResynchronizingAjaxController());
//设置需要抓取那个网站的数据
String url = "http://www.cninfo.com.cn/search/search.jsp";
//获取该网站的数据并保存在htmlPage中
HtmlPage htmlPage= webClient.getPage(url);
//该方法在getPage()方法之后调用才能生效
webClient.waitForBackgroundJavaScript(1000*3);
webClient.setJavaScriptTimeout(0);
//选中创业板的select
if(page == 1){
//设置时间
//获取name为startTime的input标签,获取标签的方法有三种ID,Name,class
HtmlInput starttime = htmlPage.getElementByName("startTime");
//设置input标签的值为
starttime.setValueAttribute("2016-12-21");
HtmlInput endtime = htmlPage.getElementByName("endTime");
endtime.setValueAttribute("2016-12-21");
//获取ID为marketType的标签
DomElement select = htmlPage.getElementById("marketType");
//获取所有的option标签
DomNodeList listSelect = select.getElementsByTagName("option");
for(int i = 0;i < listSelect.size();i++){
//设置选中哪一个select中的option
if(i==3){
HtmlOption htmlOption = (HtmlOption) listSelect.get(i);
htmlOption.setSelected(true);
}
}
//根据ID得到form表单
HtmlForm form = htmlPage.getFormByName("queryHistoryForm");
//点击查询按钮
HtmlButtonInput button = form.getInputByValue("查询");
//提交form表单,并将获取到的数据重新赋值给htmlPage
htmlPage = button.click();
}
//解析获取的数据,可以通过一层一层的解析来获取数据,也可以获取整个的网页数据,然后通过正则表达式来解析网页提取需要的数据
//获取所有为table标签
DomNodeList list = htmlPage.getElementsByTagName("table");
//获取第二个table标签
DomElement element = (DomElement) list.get(1);
//获取table标签中的tr标签
DomNodeList elementTr = element.getElementsByTagName("tr");
String code = "";
String title = "";
String titleHref = "";
String timedata = "";
//遍历table标签中的tr标签
for(int i = 0;i<elementTr.size();i++){
DomElement elementTd = (DomElement) elementTr.get(i);
DomNodeList listTd = elementTd.getElementsByTagName("td");
for(int j = 0;j<listTd.size();j++){
DomElement domElement = (DomElement) listTd.get(j);
if(j==0){
code = domElement.asText();
}else if(j==1){
title = domElement.asText();
titleHref = "http://www.cninfo.com.cn" + elementTd.getElementsByTagName("a").get(0).getAttribute("href");
}else if(j == 2){
timedata = domElement.asText();
}
//计算有多少页,下一页
DomNodeList listSpan = htmlPage.getElementsByTagName("span");
DomElement elementSpan = (DomElement) listSpan.get(4);
DomNodeList lista = elementSpan.getElementsByTagName("a");
if(page == 1){
HtmlAnchor asum;
if(lista.size()>0){
asum = (HtmlAnchor) lista.get(lista.size()-1);
sumPage = Integer.parseInt(asum.asText());
}else{
sumPage = 1;
}
//得到总共的页数
}
if(page == sumPage){
try {
book.write();
book.close();
} catch (WriteException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if(page < sumPage){
for(int i = 0;i<=sumPage-2;i++){
HtmlAnchor a = (HtmlAnchor) lista.get(i);
String pageStr = a.asText();
if(page+1 == Integer.parseInt(pageStr)){
htmlPage.cleanUp();
htmlPage = a.click();
page++;
obtaindataBypage(file,book,sheet);
}
}
}
//关闭浏览器对象
webClient.close();
总结:我们可以通过获取a标签,然后再获取点击a标签之后的页面,代表如下:
HtmlAnchor anchor = (HtmlAnchor) item.getChildNodes().get(0);
HtmlPage htmlPage = anchor.click();
获取点击之后的页面数据之后,最好使用Thread.slepp(3000)使当前线程休眠一段时间,保证数据能够被加载出来。
下面是整个项目的地址:http://download.csdn.net/detail/sinat_29957455/9892512