1. 什么是HtmlUnit?

HtmlUnit是一个无界面浏览器Java程序。它为HTML文档建模,提供了调用页面、填写表单、单击链接等操作的API。就跟你在浏览器里做的操作一样。HtmlUnit不错的JavaScript支持(不断改进),甚至可以使用相当复杂的Ajax库,根据配置的不同模拟Chrome、Firefox或Internet Explorer等浏览器。HtmlUnit通常用于测试或从web站点检索信息。

2. 它可以干啥?

  • 它可以读取页面所有元素

    eg:现在有一个需求是客户给了一个.chm说明文档,文件中记录了表和字段的关系和注释,现在需要将注释添加到数据库中,首先可以通过工具将chm文件转换成html文件,然后我们就可以通过爬取html文件实现这个功能;

  • 它可以模拟用户进行点击,这个功能就可以实现登录,跳转页面等等;

    eg:现在有一个需求是客户那边有一个系统里边包含了很多数据,但是因为安全性问题我们的系统不能够直连它的数据库,所以现在需要实时的展示客户那边系统的数据,需要怎么做呢?可以通过爬虫做一个 “适配器”,它的大致原理是 当用户点击我们的系统点击查看 “人员信息” 时,我们的系统通过爬虫实时获取客户系统页面上的数据,在返回给我们的系统进行展示。

    3. 大体流程

    需求:现在想通过Java程序实现爬取新浪新闻的一些内容

  • 创建新浪网站实例
  • 通过表达式获取你想获取的标签元素
  • 4. 项目代码

  • pom文件

    <dependency>
                <groupId>net.sourceforge.htmlunit</groupId>
                <artifactId>htmlunit</artifactId>
                <version>2.23</version>
    </dependency>
    
    public class XinLangNews {
        public static void main(String args[]) throws Exception {
            //创建web客户端
            WebClient webClient = new WebClient(BrowserVersion.CHROME);//新建一个模拟谷歌Chrome浏览器的浏览器客户端对象
            webClient.getOptions().setThrowExceptionOnScriptError(false);//当JS执行出错的时候是否抛出异常, 这里选择不需要
            webClient.getOptions().setThrowExceptionOnFailingStatusCode(false);//当HTTP的状态非200时是否抛出异常, 这里选择不需要
            webClient.getOptions().setActiveXNative(false);
            webClient.getOptions().setCssEnabled(false);//是否启用CSS, 因为不需要展现页面, 所以不需要启用
            webClient.getOptions().setJavaScriptEnabled(true); //很重要,启用JS
            webClient.setAjaxController(new NicelyResynchronizingAjaxController());//很重要,设置支持AJAX
           webClient.waitForBackgroundJavaScript(30000);//异步JS执行需要耗时,所以这里线程要阻塞30秒,等待异步JS执行结束
            //设置链接地址,并返回网站实例
            HtmlPage page = webClient.getPage("https://news.sina.com.cn/");
            // 获取里边所有的span
            List<HtmlSpan> byXPath = (List<HtmlSpan>) page.getByXPath("//*[@id=\"blk_cNav2_01\"]/div/a/span");
            // 遍历所有span并打印出里边的内容
            byXPath.forEach((x) -> {
                System.out.println(x.getTextContent());
    

    注意:运行的时候控制台可能很多报错,不要慌,这些错是html页面上js报的错

    说明:下面这三步很重要,它可以读取到js和ajax动态加载的内容

    webClient.getOptions().setJavaScriptEnabled(true); //很重要,启用JS
    webClient.setAjaxController(new NicelyResynchronizingAjaxController());//很重要,设置支持AJAX
    webClient.waitForBackgroundJavaScript(30000);//异步JS执行需要耗时,所以这里线程要阻塞30秒,等待异步JS执行结束,具体时间可以根据网页js加载效率动态调整,如果有页面元素获取不到的情况,可能是这里出问题了
    

    5. 奇淫技巧

    在用HtmlUnit写一个爬虫项目的时候,创建WebClient客户端基本都是固定格式,最麻烦的还是获取dom元素,这里我讲介绍一种非常方便的获取dom元素的方法;这里我通过上面的新浪新闻网站进行介绍;

    首先打开chrome,然后进入到https://news.sina.com.cn/,按F12打开开发者模式,找到你想要获取到的页面元素,此时在chrome的Elements模块中选择需要获取的元素点击“右键”,选择Copy-->Copy XPath,此时就获取到了该元素在整个页面的xpath路径,图中 “滚动” 的xpath路径为 //[@id="blk_cNav2_01"]/div/a[1]/span,由于我想获取所有span(也就是 滚动,排行,政务等等),所以可以将上面复制过来的xpath路径改写为//[@id="blk_cNav2_01"]/div/a/span,把a[1]改成a即可,此时大功告成。你们可以通过这个方法快速准确的定位到元素

    6. 未完待续

    比如Jsoup,WebClient和HttpClient都可以实现页面爬虫效果,但是他们有什么区别呢?这篇文章将在下期揭晓;

    本文使用 mdnice 排版

    分类:
    后端
    标签:
  •