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

 

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

 

下面看看HtmlUnit的效果如何:

 

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

 

Xml代码  
收藏代码
  1. <dependency>  
  2.     <groupId>junit</groupId>  
  3.     <artifactId>junit</artifactId>  
  4.     <version>4.8.2</version>  
  5.     <scope>test</scope>  
  6. </dependency>  
  7. <dependency>  
  8.     <groupId>net.sourceforge.htmlunit</groupId>  
  9.     <artifactId>htmlunit</artifactId>  
  10.     <version>2.14</version>  
  11. </dependency>  

 

 

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

 

Java代码  
  1. /** 
  2.  * 使用HtmlUnit模拟浏览器执行JS来获取网页内容 
  3.  * @author 杨尚川 
  4.  */  
  5. public class HtmlUnitTest {  
  6.     @Test  
  7.     public void homePage() throws Exception {  
  8.         final WebClient webClient = new WebClient(BrowserVersion.INTERNET_EXPLORER_11);  
  9.         final HtmlPage page = webClient.getPage("http://yangshangchuan.iteye.com");  
  10.         Assert.assertEquals("杨尚川的博客 - ITeye技术网站", page.getTitleText());  
  11.         final String pageAsXml = page.asXml();  
  12.         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等框架的解决方案、技术支持、技术咨询以及培训等服务。"));  
  13.         final String pageAsText = page.asText();  
  14.         Assert.assertTrue(pageAsText.contains("[置顶] 国内首套免费的《Nutch相关框架视频教程》(1-20)"));  
  15.         webClient.closeAllWindows();  
  16.     }  
  17.     @Test  
  18.     public void homePage_Firefox() throws Exception {  
  19.         final WebClient webClient = new WebClient(BrowserVersion.FIREFOX_24);  
  20.         final HtmlPage page = webClient.getPage("http://yangshangchuan.iteye.com");      
  21.         Assert.assertEquals("杨尚川的博客 - ITeye技术网站", page.getTitleText());  
  22.         webClient.closeAllWindows();  
  23.     }  
  24.     @Test  
  25.     public void getElements() throws Exception {  
  26.         final WebClient webClient = new WebClient(BrowserVersion.CHROME);  
  27.         final HtmlPage page = webClient.getPage("http://yangshangchuan.iteye.com");  
  28.         final HtmlDivision div = page.getHtmlElementById("blog_actions");  
  29.         //获取子元素  
  30.         Iterator<DomElement> iter = div.getChildElements().iterator();  
  31.         while(iter.hasNext()){  
  32.             System.out.println(iter.next().getTextContent());  
  33.         }  
  34.         //获取所有输出链接  
  35.         for(HtmlAnchor anchor : page.getAnchors()){  
  36.             System.out.println(anchor.getTextContent()+" : "+anchor.getAttribute("href"));  
  37.         }  
  38.         webClient.closeAllWindows();  
  39.     }  
  40.     @Test  
  41.     public void xpath() throws Exception {  
  42.         final WebClient webClient = new WebClient();  
  43.         final HtmlPage page = webClient.getPage("http://yangshangchuan.iteye.com");  
  44.         //获取所有博文标题  
  45.         final List<HtmlAnchor> titles = (List<HtmlAnchor>)page.getByXPath("/html/body/div[2]/div[2]/div/div[16]/div/h3/a");  
  46.         for(HtmlAnchor title : titles){  
  47.             System.out.println(title.getTextContent()+" : "+title.getAttribute("href")); 
  48.         }  
  49.         //获取博主信息  
  50.         final HtmlDivision div = (HtmlDivision) page.getByXPath("//div[@id='blog_owner_name']").get(0);  
  51.         System.out.println(div.getTextContent());  
  52.         webClient.closeAllWindows();  
  53.     }  
  54.     @Test  
  55.     public void submittingForm() throws Exception {  
  56.         final WebClient webClient = new WebClient(BrowserVersion.FIREFOX_24);  
  57.         final HtmlPage page = webClient.getPage("http://www.oschina.net");  
  58.         // Form没有name和id属性  
  59.         final HtmlForm form = page.getForms().get(0);  
  60.         final HtmlTextInput textField = form.getInputByName("q");  
  61.         final HtmlButton button = form.getButtonByName("");  
  62.         textField.setValueAttribute("APDPlat");  
  63.         final HtmlPage resultPage = button.click();  
  64.         final String pageAsText = resultPage.asText();  
  65.         Assert.assertTrue(pageAsText.contains("找到约"));  
  66.         Assert.assertTrue(pageAsText.contains("条结果"));          
  67.         webClient.closeAllWindows();  
  68.     }  
  69. }  

 

 

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