文档章节

模拟浏览器的神器 - HtmlUnit

杨尚川
 杨尚川
发布于 2014/04/04 03:00
字数 684
阅读 3105
收藏 13

随着Web的发展,RIA越来越多,JavaScript和Complex AJAX Libraries给网络爬虫带来了极大的挑战,解析页面的时候需要模拟浏览器执行JavaScript才能获得需要的文本内容。

 

好在有一个Java开源项目HtmlUnit,它能模拟Firefox、IE、Chrome等浏览器,不但可以用来测试Web应用,还可以用来解析包含JS的页面以提取信息。

 

下面看看HtmlUnit的效果如何:

 

首先,建立一个maven工程,引入junit依赖和HtmlUnit依赖:

 

<dependency>
	<groupId>junit</groupId>
	<artifactId>junit</artifactId>
	<version>4.8.2</version>
	<scope>test</scope>
</dependency>
<dependency>
	<groupId>net.sourceforge.htmlunit</groupId>
	<artifactId>htmlunit</artifactId>
	<version>2.14</version>
</dependency>

 

 

其次,写一个junit单元测试来使用HtmlUnit提取页面信息:

 

/**
 * 使用HtmlUnit模拟浏览器执行JS来获取网页内容
 * @author 杨尚川
 */
public class HtmlUnitTest {
    @Test
    public void homePage() throws Exception {
        final WebClient webClient = new WebClient(BrowserVersion.INTERNET_EXPLORER_11);
        final HtmlPage page = webClient.getPage("http://yangshangchuan.iteye.com");
        Assert.assertEquals("杨尚川的博客 - ITeye技术网站", page.getTitleText());
        final String pageAsXml = page.asXml();
        Assert.assertTrue(pageAsXml.contains("杨尚川,系统架构设计师,系统分析师,2013年度优秀开源项目APDPlat发起人,资深Nutch搜索引擎专家。多年专业的软件研发经验,从事过管理信息系统(MIS)开发、移动智能终端(Win CE、Android、Java ME)开发、搜索引擎(nutch、lucene、solr、elasticsearch)开发、大数据分析处理(Hadoop、Hbase、Pig、Hive)等工作。目前为独立咨询顾问,专注于大数据、搜索引擎等相关技术,为客户提供Nutch、Lucene、Hadoop、Solr、ElasticSearch、HBase、Pig、Hive、Gora等框架的解决方案、技术支持、技术咨询以及培训等服务。"));
        final String pageAsText = page.asText();
        Assert.assertTrue(pageAsText.contains("[置顶] 国内首套免费的《Nutch相关框架视频教程》(1-20)"));
        webClient.closeAllWindows();
    }
    @Test
    public void homePage_Firefox() throws Exception {
        final WebClient webClient = new WebClient(BrowserVersion.FIREFOX_24);
        final HtmlPage page = webClient.getPage("http://yangshangchuan.iteye.com");        
        Assert.assertEquals("杨尚川的博客 - ITeye技术网站", page.getTitleText());
        webClient.closeAllWindows();
    }
    @Test
    public void getElements() throws Exception {
        final WebClient webClient = new WebClient(BrowserVersion.CHROME);
        final HtmlPage page = webClient.getPage("http://yangshangchuan.iteye.com");
        final HtmlDivision div = page.getHtmlElementById("blog_actions");
        //获取子元素
        Iterator<DomElement> iter = div.getChildElements().iterator();
        while(iter.hasNext()){
            System.out.println(iter.next().getTextContent());
        }
        //获取所有输出链接
        for(HtmlAnchor anchor : page.getAnchors()){
            System.out.println(anchor.getTextContent()+" : "+anchor.getAttribute("href"));
        }
        webClient.closeAllWindows();
    }
    @Test
    public void xpath() throws Exception {
        final WebClient webClient = new WebClient();
        final HtmlPage page = webClient.getPage("http://yangshangchuan.iteye.com");
        //获取所有博文标题
        final List<HtmlAnchor> titles = (List<HtmlAnchor>)page.getByXPath("/html/body/div[2]/div[2]/div/div[16]/div/h3/a");
        for(HtmlAnchor title : titles){
            System.out.println(title.getTextContent()+" : "+title.getAttribute("href"));
        }
        //获取博主信息
        final HtmlDivision div = (HtmlDivision) page.getByXPath("//div[@id='blog_owner_name']").get(0);
        System.out.println(div.getTextContent());
        webClient.closeAllWindows();
    }
    @Test
    public void submittingForm() throws Exception {
        final WebClient webClient = new WebClient(BrowserVersion.FIREFOX_24);
        final HtmlPage page = webClient.getPage("http://www.oschina.net");
        // Form没有name和id属性
        final HtmlForm form = page.getForms().get(0);
        final HtmlTextInput textField = form.getInputByName("q");
        final HtmlButton button = form.getButtonByName("");
        textField.setValueAttribute("APDPlat");
        final HtmlPage resultPage = button.click();
        final String pageAsText = resultPage.asText();
        Assert.assertTrue(pageAsText.contains("找到约"));
        Assert.assertTrue(pageAsText.contains("条结果"));        
        webClient.closeAllWindows();
    }
}

 

 

最后,我们运行单元测试, 全部通过测试! 

 



 

© 著作权归作者所有

杨尚川

杨尚川

粉丝 1102
博文 220
码字总数 1624053
作品 12
东城
架构师
私信 提问
加载中

评论(6)

Maven4
Maven4
如果所有的网页都需要认证的话就比较难了。。。
well
well
不知道大规模抓取上效率如何?如果应用到分布式爬取上,js css 重复获取带来的性能怎样?
Linesh
Linesh

引用来自“CodeCleaner”的评论

你就说这代码怎么看吧

引用来自“杨尚川”的评论

怎么了?你用手机看不了吗?
抱歉,现在看到了。嗯是关于HtmlUtil的代码,感谢博主的分享
杨尚川
杨尚川 博主

引用来自“CodeCleaner”的评论

你就说这代码怎么看吧
怎么了?你用手机看不了吗?
Linesh
Linesh
你就说这代码怎么看吧
maiyang
maiyang
收藏
HtmlUnit 网络爬虫 菜鸟的学习笔记(一)

什么是HtmlUnit HtmlUnit是一个开源的浏览器模拟工具,可以方便我们模拟浏览器的行为,例如打开网页,提交表单等,这样我们可以用他来爬网页 官网下载:http://htmlunit.sourceforge.net/ ja...

木有芒果
2015/08/31
502
0
HtmlUnit 2.6发布

HtmlUnit 是 JUnit 的扩展测试框架之一。HtmlUnit 将返回文档模拟成 HTML,这样您便可以直接处理这些文档了。HtmlUnit 使用例如 table、form 等标识符将测试文档作为 HTML 来处理。它同样需要...

红薯
2009/09/07
3.3K
0
HtmlUnit 2.8 发布,Java的Web单元测试

HtmlUnit 是 JUnit 的扩展测试框架之一。HtmlUnit 将返回文档模拟成 HTML,这样您便可以直接处理这些文档了。HtmlUnit 使用例如 table、form 等标识符将测试文档作为 HTML 来处理。它同样需要...

红薯
2010/08/12
2.2K
0
Nutch-Htmlunit 1.8 发布:基于Apache Nutch和Htmlunit的扩展实现AJAX页面爬虫抓取解析插件

之前提供了一个版本,是直接把plugin形式的源码放到代码库,后来发现有不少人反馈说自己集成到apache nutch中编译或运行,遇到这那的问题。因此这次干脆基于Apache Nutch 1.8源码工程,把所有...

EntDIY
2014/08/08
3.8K
11
基于Apache Nutch和Htmlunit的扩展实现AJAX页面爬虫抓取解析插件

之前提供了一个版本,是直接把plugin形式的源码放到代码库,后来发现有不少人反馈说自己集成到apache nutch中编译或运行,遇到这那的问题。因此这次干脆基于Apache Nutch 1.8源码工程,把所有...

EntDIY
2014/08/07
2.8K
4

没有更多内容

加载失败,请刷新页面

加载更多

矩阵中的路径

判断在一个矩阵中是否存在一条包含某字符串所有字符的路径。路径可以从矩阵中的任意一个格子开始,每一步可以在矩阵中向上下左右移动一个格子。如果一条路径经过了矩阵中的某一个格子,则该路...

Garphy
17分钟前
4
0
Hibernate 5 Maven 仓库的 Artifacts

Hibernate artifacts 官方发布的仓库在 JBoss Maven repository 中。Hibernate 发布的 artifacts 也会同时同步到 Maven Central 仓库中,这是一个自动同步进程(可能会有一些延迟)。 Hibern...

honeymoose
今天
5
0
如何学习uni-app?

uni-app 是一个使用 Vue.js 开发跨平台应用的前端框架。 开发者通过编写 Vue.js 代码,uni-app 将其编译到iOS、Android、微信小程序、H5等多个平台,保证其正确运行并达到优秀体验。 <templ...

达叔小生
今天
6
0
OSChina 周一乱弹 —— 后来马云就一心想挣钱了

Osc乱弹歌单(2019)请戳(这里) 【今日歌曲】 小小编辑:《空帆船》- 朴树 《空帆船》- 朴树 手机党少年们想听歌,请使劲儿戳(这里) @webw :第二次被锁在电梯里了 上次你忘带电梯卡, ...

小小编辑
今天
1K
15
关于does not give a valid preprocessing token

#define VFUNC(self) ((##self##)->_vptr) 这样在gcc下会编译失败, VC不会 报pasting ) does not give a valid preprocessing token 据说是因为版本问题 解法:去掉## define VFUNC(self) (......

shzwork
今天
5
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部