欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

HtmlUnit(基于java)网络爬虫总结

程序员文章站 2022-03-02 21:13:43
...

HtmlUnit(基于java)网络爬虫总结

简介
HtmlUnit是一个没有界面的第三方爬虫框架,它模拟浏览器,在后台创建一个开发者想要的浏览器类型,与远程地址发起请求,并且自带js解析等功能,非常好用。下面我就说说HtmlUnit的基本使用和过程中可能会出现的问题。
一、环境引入
因为我是在我自己的spring boot项目在引入的,所以我在pom文件中加入依赖就行了


   <dependency>
        <groupId>net.sourceforge.htmlunit</groupId>
        <artifactId>htmlunit</artifactId>
        <version>2.41.0</version>
    </dependency>

如果你只是爬取一个js不多的网站我建议换下面这个依赖


        <dependency>
            <groupId>net.sourceforge.htmlunit</groupId>
            <artifactId>htmlunit</artifactId>
            <version>2.23</version>
        </dependency>

两者的区别我后面会讲,当然如果你不是用的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查询:

 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<DomNode> 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”)返回htmlPage下面第一个class为submit的div标签
htmlPage .querySelector(“div[id=‘submit’]”)返回htmlPage下面第一个id为submit的div标签
以上的列举方法相信已经够用,不够的可以参阅css选择器
以下列举常见的html标签与HtmlUnit类的对应关系

div -> HtmlDivision
div集合 -> DomNodeList<DomNode>
fieldSet -> HtmlFieldSet 
form -> HtmlForm
button -> HtmlButton
a -> HtmlAnchor
<input type="xxx"> -> HtmlXxxInput
(<input type="text"> -> HtmlTextInput)
table -> HtmlTable
tr -> HtmlTableRow
td -> TableDataCell

有 setAttribute()方法节点的属性样式,setNodeValue()设置节点value值。是不是英语一下子就提高了?几乎所有的标签可以找到与之对应的的类,下面看我的实战:这是一个在线填写温度的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使用的,比较好用,这里就不列举。

如果你对文章比较满意,欢迎点赞! thanks