`

模拟浏览器的神器 - HtmlUnit

阅读更多

随着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();
    }
}

 

 

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

 

 

 

 

 

 

 

 

 

 

4
6
分享到:
评论
3 楼 无奈的漂泊 2014-04-30  
你好,我想问下简历解析(各样的格式)如果能解析出准确的数据,有什么好的办法吗,我再看你有发分词解析的文章,因为不同的简历关键字可能不一样(可能叫姓名或者名字),要定义个字典?请指导指导。
2 楼 yangshangchuan 2014-04-04  
llcode 写道
杨总,你好。我最近在做爬虫的动态页面解析这块。看到java有个HtmlUnit项目,可以实现无界面的浏览器,貌似功能还不错。但我使用了一下,发现速度很慢,而且对js的支持也不是特别好。有个问题想咨询下你:
目前的生产环境中的爬虫对动态页面解析是怎么处理的?比如抓某个页面的外链接,很多的外链接存在于js中,没办法直接从页面源码中得到。对于这个,有什么思路和建议吗?

这个跟生产环境没有什么关系,跟你的业务要求有关系。
用一个开源项目,首先要评估它是否能满足你的业务需求。如果满足不了,那么就需要接着评估自己是否有能力基于开源项目来定制开发;如果不能,那么看是否能找到相应的人来帮你;如果还是不行,可以考虑商业采购。
1 楼 llcode 2014-04-04  
杨总,你好。我最近在做爬虫的动态页面解析这块。看到java有个HtmlUnit项目,可以实现无界面的浏览器,貌似功能还不错。但我使用了一下,发现速度很慢,而且对js的支持也不是特别好。有个问题想咨询下你:
目前的生产环境中的爬虫对动态页面解析是怎么处理的?比如抓某个页面的外链接,很多的外链接存在于js中,没办法直接从页面源码中得到。对于这个,有什么思路和建议吗?

相关推荐

Global site tag (gtag.js) - Google Analytics