java爬虫抓取网页数据(1.HtmlUnit中文文档获取页面中特定的元素tips:1.)
优采云 发布时间: 2021-11-13 18:01java爬虫抓取网页数据(1.HtmlUnit中文文档获取页面中特定的元素tips:1.)
1.HtmlUnit 简介
HtmlUnit 是一个 Java 无界面浏览器库。它模拟 HTML 文档并提供相应的 API,让您可以像在“普通”浏览器中一样调用页面、填写表单、单击链接等。它有很好的 JavaScript 支持(仍在改进),甚至可以处理相当复杂的 AJAX 库,根据使用的配置模拟 Chrome、Firefox 或 Internet Explorer。它通常用于测试目的或从 网站 检索信息。
HtmlUnit 不是通用的单元测试框架。它是一种模拟浏览器以进行测试的方法,旨在用于另一个测试框架(例如 JUnit 或 TestNG)。有关介绍,请参阅文档“HtmlUnit 入门”。HtmlUnit 用作不同的开源工具,例如 Canoo WebTest、JWebUnit、WebDriver、JSFUnit、WETATOR、Celerity、Spring MVC Test HtmlUnit 作为底层“浏览器”。
HtmlUnit 最初由 Gargoyle Software 的 Mike Bowler 编写,并在 Apache 2 许可下发布。从那以后,它收到了许多其他开发者的贡献,今天也将得到他们的帮助。
几年前,在做购物网站的数据采集工作时,我偶然遇到了HtmlUnit。我记得我如何无法捕获页面上的价格数据,并且 httpfox 无法跟踪价格数据的 URL。就在我不知所措的时候,HtmlUnit出现了,帮我解决了问题。所以今天我想说声谢谢,并向大家推荐HtmlUnit。
2.htmlUnit中文文档
3.1 获取页面的 TITLE、XML 代码和文本
import com.gargoylesoftware.htmlunit.WebClient;
import com.gargoylesoftware.htmlunit.html.HtmlPage;
import com.gargoylesoftware.htmlunit.BrowserVersion;
import com.gargoylesoftware.htmlunit.html.HtmlDivision;
import com.gargoylesoftware.htmlunit.html.HtmlAnchor;
import com.gargoylesoftware.htmlunit.*;
import com.gargoylesoftware.htmlunit.WebClientOptions;
import com.gargoylesoftware.htmlunit.html.HtmlInput;
import com.gargoylesoftware.htmlunit.html.HtmlBody;
import java.util.List;
public class helloHtmlUnit{
public static void main(String[] args) throws Exception{
String str;
//创建一个webclient
WebClient webClient = new WebClient();
//htmlunit 对css和javascript的支持不好,所以请关闭之
webClient.getOptions().setJavaScriptEnabled(false);
webClient.getOptions().setCssEnabled(false);
//获取页面
HtmlPage page = webClient.getPage("http://www.baidu.com/");
//获取页面的TITLE
str = page.getTitleText();
System.out.println(str);
//获取页面的XML代码
str = page.asXml();
System.out.println(str);
//获取页面的文本
str = page.asText();
System.out.println(str);
//关闭webclient
webClient.closeAllWindows();
}
}
3.2 使用不同版本的浏览器打开
import com.gargoylesoftware.htmlunit.WebClient;
import com.gargoylesoftware.htmlunit.html.HtmlPage;
import com.gargoylesoftware.htmlunit.BrowserVersion;
import com.gargoylesoftware.htmlunit.html.HtmlDivision;
import com.gargoylesoftware.htmlunit.html.HtmlAnchor;
import com.gargoylesoftware.htmlunit.*;
import com.gargoylesoftware.htmlunit.WebClientOptions;
import com.gargoylesoftware.htmlunit.html.HtmlInput;
import com.gargoylesoftware.htmlunit.html.HtmlBody;
import java.util.List;
public class helloHtmlUnit{
public static void main(String[] args) throws Exception{
String str;
//使用FireFox读取网页
WebClient webClient = new WebClient(BrowserVersion.FIREFOX_24);
//htmlunit 对css和javascript的支持不好,所以请关闭之
webClient.getOptions().setJavaScriptEnabled(false);
webClient.getOptions().setCssEnabled(false);
HtmlPage page = webClient.getPage("http://www.baidu.com/");
str = page.getTitleText();
System.out.println(str);
//关闭webclient
webClient.closeAllWindows();
}
}
3.3 在页面上查找特定元素
public class helloHtmlUnit{
public static void main(String[] args) throws Exception{
//创建webclient
WebClient webClient = new WebClient(BrowserVersion.CHROME);
//htmlunit 对css和javascript的支持不好,所以请关闭之
webClient.getOptions().setJavaScriptEnabled(false);
webClient.getOptions().setCssEnabled(false);
HtmlPage page = (HtmlPage)webClient.getPage("http://www.baidu.com/");
//通过id获得"百度一下"按钮
HtmlInput btn = (HtmlInput)page.getHtmlElementById("su");
System.out.println(btn.getDefaultValue());
//关闭webclient
webClient.closeAllWindows();
}
}
提示:某些元素中没有id和name或其他节点。您可以通过查找其子节点和父节点之间的规则来获取元素。具体方法请参考:
核心代码是:
final HtmlPage nextPage = ((DomElement)(htmlpage.getElementByName("key").getParentNode().getParentNode())).getLastElementChild().click();
3.4 元素搜索
public class helloHtmlUnit{
public static void main(String[] args) throws Exception{
//创建webclient
WebClient webClient = new WebClient(BrowserVersion.CHROME);
//htmlunit 对css和javascript的支持不好,所以请关闭之
webClient.getOptions().setJavaScriptEnabled(false);
webClient.getOptions().setCssEnabled(false);
HtmlPage page = (HtmlPage)webClient.getPage("http://www.baidu.com/");
//查找所有div
List hbList = page.getByXPath("//div");
HtmlDivision hb = (HtmlDivision)hbList.get(0);
System.out.println(hb.toString());
//查找并获取特定input
List inputList = page.getByXPath("//input[@id='su']");
HtmlInput input = (HtmlInput)inputList.get(0);
System.out.println(input.toString());
//关闭webclient
webClient.closeAllWindows();
}
}
3.5 提交搜索
public class helloHtmlUnit{
public static void main(String[] args) throws Exception{
//创建webclient
WebClient webClient = new WebClient(BrowserVersion.CHROME);
//htmlunit 对css和javascript的支持不好,所以请关闭之
webClient.getOptions().setJavaScriptEnabled(false);
webClient.getOptions().setCssEnabled(false);
HtmlPage page = (HtmlPage)webClient.getPage("http://www.baidu.com/");
//获取搜索输入框并提交搜索内容
HtmlInput input = (HtmlInput)page.getHtmlElementById("kw");
System.out.println(input.toString());
input.setValueAttribute("ymd");
System.out.println(input.toString());
//获取搜索按钮并点击
HtmlInput btn = (HtmlInput)page.getHtmlElementById("su");
HtmlPage page2 = btn.click();
//输出新页面的文本
System.out.println(page2.asText());
}
}
3.htmlUnit方法介绍
一、环境介绍
因为是在自己的spring boot项目中引入的,所以只是在pom文件中添加了依赖。
net.sourceforge.htmlunit
htmlunit
2.41.0
如果你只是爬一个网站 js不多,建议改下下面的依赖
net.sourceforge.htmlunit
htmlunit
2.23
后面我会讲到两者的区别。当然,如果你不是使用maven项目(没有pom),可以到官网下载源码库
二、使用
HtmlUnit使用起来非常简单,使用的时候可以去官网手册查一下语法。其实说明书只是介绍介绍,下面听我说就够了;
1、创建客户端并配置客户端
final String url ="https:****";//大家这可以填自己爬虫的地址
WebClient webClient = new WebClient(BrowserVersion.FIREFOX_68);//创建火狐浏览器 2.23版本是FIREFOX_45 new不写参数是默认浏览器
webClient.getOptions().setCssEnabled(false);//(屏蔽)css 因为css并不影响我们抓取数据 反而影响网页渲染效率
webClient.getOptions().setThrowExceptionOnScriptError(false);//(屏蔽)异常
webClient.getOptions().setThrowExceptionOnFailingStatusCode(false);//(屏蔽)日志
webClient.getOptions().setJavaScriptEnabled(true);//加载js脚本
webClient.getOptions().setTimeout(50000);//设置超时时间
webClient.setAjaxController(new NicelyResynchronizingAjaxController());//设置ajax
HtmlPage htmlPage = webClient.getPage(url);//将客户端获取的树形结构转化为HtmlPage
Thread.sleep(10000);//主线程休眠10秒 让客户端有时间执行js代码 也可以写成webClient.waitForBackgroundJavaScript(1000)
下面是一个等待js执行的情况,2.41.0很适合很多js的情况,但是2.3总是有问题,无法刷新网页,2.@ >41.0 打印的也很详细,执行的过程也比较慢,可能会比较慢产生详细的作品
远程地址页面在此处获取。我们现在需要做的是解析dom节点并填写数据来模拟点击等事件。如果要打印 htmlPage.asText() 输出 htmlPage 节点的文本 htmlPage.asXml() 输出 htmlPage 节点的 xml 代码
2、 获取节点
建议在这个链接准备一些前端知识
HtmlUnit给出了两种获取节点的方式
XPath 查询:
更详细的xpath解释:
final HtmlPage page = webClient.getPage("http://htmlunit.sourceforge.net");
//get list of all divs
final List divs = htmlPage .getByXPath("//div");
//get div which has a 'name' attribute of 'John'
final HtmlDivision div = (HtmlDivision) htmlPage .getByXPath("//div[@name='John']").get(0);
css 选择器:(我更喜欢它)
final DomNodeList divs = htmlPage .querySelectorAll("div");
for (DomNode div : divs) {
....
}
//get div which has the id 'breadcrumbs'
final DomNode div = htmlPage .querySelector("div#breadcrumbs");
css 提供了一个集合查询 querySelectorAll 和一个单一查询 querySelector。如果你没有基础,我给你举个例子:
htmlPage .querySelectorAll("div") 返回 htmlPage 下的一组 div 标签
htmlPage .querySelector("div:nth-child(1)") 返回htmlPage下div的第一个div
htmlPage .querySelector(".submit") 返回htmlPage下的第一个class=submit标签
htmlPage .querySelector("#submit") 返回 htmlPage 下 id=submit 的第一个标签
htmlPage .querySelector("div.submit") 返回类为submit的htmlPage下的第一个div标签
htmlPage .querySelector("div[id='submit']") 返回htmlPage下第一个id为submit的div标签
上面的枚举方法相信已经足够了,如果还不够,可以参考css选择器
下面列出常见的html标签与HtmlUnit类的对应关系
div -> HtmlDivision
div集合 -> DomNodeList
fieldSet -> HtmlFieldSet
form -> HtmlForm
button -> HtmlButton
a -> HtmlAnchor
-> HtmlXxxInput
( -> HtmlTextInput)
table -> HtmlTable
tr -> HtmlTableRow
td -> TableDataCell
setAttribute()方法有节点的属性样式,setNodeValue()设置节点的值。你的英语一下子提高了吗?几乎所有的标签都能找到对应的类别。来看看我的实战:这是一个在线填写温度的excel文档。如果访问更改地址,他会在登录页面提示一个登录按钮。登录按钮,我们现在模拟打开自动登录框:
//这段代码是为了让网页的的某个按钮加载出来之后再执行下面的代码
while (htmlPage.querySelector("#header-login-btn")==null) {
synchronized (htmlPage) {
htmlPage.wait(1000);
}
}
HtmlButton login = htmlPage.querySelector("#header-login-btn");//获取到登陆按钮
if (login!=null){//如果网页上没这个按钮你还要去获取他只会得到一个空对象,所以我们用空的方式可以判断网页上是否有这个按钮
System.out.println("-----未登录测试-----");
htmlPage=login.click();//模拟按钮点击后要将网页返回回来方便动态更新数据
System.out.println(htmlPage.asText());
HtmlAnchor switcher_plogin = htmlPage.querySelector("a[id='switcher_plogin']");
if (switcher_plogin!=null) {//帐号密码登录
System.out.println("-----点击了帐号密码登陆-----");
htmlPage = switcher_plogin.click();
System.out.println(htmlPage.asText());
}
}
System.out.println(htmlPage.asText());
webClient.close();
爬虫最重要的一步就是我们首先调试网页,有哪些按钮,点击哪些,设置哪些值。毕竟,我们必须用代码来安排代码。
**扩展:** 如果你想从网页上获取数据或下载文件,HtmlUnit 分析是不够的。推荐使用 Jsoup 库,可以和 HtmlUnit 一起使用。使用起来比较方便,这里就不一一列举了。
三、实现一个小demo
注意:htmlunit引用的jar包不完整会导致奇怪的错误
使用maven方法更方便
参考: