【转】HtmlUnit入门教程

转载出处:http://blog.csdn.net/wxl901018/article/details/44133873

1. 简介

htmlunit是一款开源的Java页面分析工具,读取页面后,可以有效的使用htmlunit 分析页面上的内容。项目可以模拟浏览器运行,被誉为Java浏览器的开源实现。这个没有界面的浏览器,运行速度也是非常迅速的。

2.起步

1.介绍

pom.xml加入的依赖

<dependency>
        <groupId>net.sourceforge.htmlunitgroupId>
        <artifactId>htmlunitartifactId>
        <version>2.23version>
    dependency>

com.gargoylesoftware.htmlunit.WebClient类是起步的关键,它是一个仿真浏览器,其将会被用来执行所有测试。
大多数的测试单元将在一个想Junit的框架下进行,所有假设所有的例子我们都这样进行。
在第一个例子中,我们创建一个web客户端,使用该客户端来下载HtmlUnit网站的首页。然后我们确保这个页面有正确的标题。注意,根据返回数据的内容类型,getPage() 可以返回不同类型的页面。在这个例子中,我们期待 text/html 内容类型的页面,以致我们可以将结果存在com.gargoylesoftware.htmlunit.html.HtmlPage。

       @Test
       publicvoid homePage() throws Exception {
          //创建web客户端
          final WebClient webClient = new WebClient();
          //设置链接地址
          final HtmlPage page =webClient.getPage("http://htmlunit.sourceforge.net");
          //断言页面的标题,不成立时报错
          Assert.assertEquals("HtmlUnit -Welcome to HtmlUnit", page.getTitleText());
          //获取页面的Xml代码
          final String pageAsXml = page.asXml();
          //断言页面包含
          Assert.assertTrue(pageAsXml.contains(""));
          //获取页面的文本内页
          final String pageAsText = page.asText();
          //断言页面内容包含
          Assert.assertTrue(pageAsText.contains("Supportfor the HTTP and HTTPS protocols"));
          //关闭所有窗口
          webClient.closeAllWindows();
       }

2.模仿特定浏览器

有时你想模仿一个特殊的浏览器,这可以通过WebClient构造函数的com.gargoylesoftware.htmlunit.BrowserVersion 参数实现,其中已经提供一些常见浏览器的常量,但是,你可以通过BrowserVersion 的实例说明创建你自己拥有的特殊版本。

       @Test
       publicvoid homePage_Firefox() throws Exception {
          //创建并指定web客户端的类型,在此为FireFox
          final WebClient webClient = new WebClient(BrowserVersion.FIREFOX_17);
          final HtmlPage page =webClient.getPage("http://htmlunit.sourceforge.net");
          Assert.assertEquals("HtmlUnit -Welcome to HtmlUnit", page.getTitleText());
          webClient.closeAllWindows();
       }

指定这个BrowserVersion 会改变用户代理发送到服务器的报头,也会改变一些JavaScript 的行为。

3.查找特殊元素

一旦有一个HtmlPage的引用,你就可以通过其中的get方法或者使用 Xpath 搜索特殊的HtmlElement.下面是一个通过ID查找div 和通过name 获取 A 标签的超链接的例子。

       @Test
       publicvoid getElements() throws Exception {
          final WebClient webClient = new WebClient();
          //将http://some_url改为一个网址,如http://www.baidu.com/
          final HtmlPage page =webClient.getPage("http://some_url");
          //将some_div_id改为特定ID。需根据page代码而定,如百度可以将id设为wrapper
          final HtmlDivision div =page.getHtmlElementById("some_div_id");
          //将anchor_name改为指定的name,也许因页面代码而定,如百度可以将其设为tj_settingicon
          final HtmlAnchor anchor =page.getAnchorByName("anchor_name");
          webClient.closeAllWindows();
       }

在更复杂的搜索中,Xpath 是建议方法,其可以在W3Schools教程中发现学习。

       @Test
       publicvoid xpath() throws Exception {
          final WebClient webClient = new WebClient();
          final HtmlPage page =webClient.getPage("http://htmlunit.sourceforge.net");
          //获取所有div的列表
          final List> divs =page.getByXPath("//div");       
          //获取有name属性为John的div
          final HtmlDivision div = (HtmlDivision)page.getByXPath("//div[@name='John']").get(0);   
          webClient.closeAllWindows();
       }

4.使用代理服务器

WebClient 的最后一个构造函数允许你指定代理服务器信息,在这种情况下,你的连接需要经过代理服务器。

       @Test
       publicvoid homePage_proxy() throws Exception {
           //需指定myProxyPort
           final WebClient webClient = new WebClient(BrowserVersion.FIREFOX_10, "myproxyserver",
              myProxyPort);
           //设置代理的用户名和密码  
           final DefaultCredentialsProvider credentialsProvider = (DefaultCredentialsProvider)webClient.getCredentialsProvider();
           credentialsProvider.addCredentials("username","password");             
           final HtmlPage page =webClient.getPage("http://htmlunit.sourceforge.net");
           Assert.assertEquals("HtmlUnit -Welcome to HtmlUnit", page.getTitleText());          
           webClient.closeAllWindows();
       }

指定这个BrowserVersion 会改变用户代理发送到服务器的报头,也会改变一些JavaScript 的行为。

5.提交表单

我们经常想改变一个表单的值并提交会服务器。下面的例子将示例你如何去做。

       @Test
       publicvoid submittingForm() throws Exception {
          final WebClient webClient = new WebClient();        
          // 获取第一页,修改http://some_url为指定连接
          final HtmlPage page1 =webClient.getPage("http://some_url");             
          // 获取我们需要处理的表单,并在里面找到提交按钮和我们需要修改的域
          //指定myform为特定name,如百度首页可为f
          final HtmlForm form =page1.getFormByName("myform");
          //指定submitbutton为指定Id,如百度首页可为su
          final HtmlSubmitInput button =form.getInputById("submitbutton");
          //获取修改域,如百度可将userid改为wd
          final HtmlTextInput textField =form.getInputByName("userid");
          // 修改域的值
          textField.setValueAttribute("root");
          // 通过点击按钮提交表单并获取返回页面
          final HtmlPage page2 = button.click();
          webClient.closeAllWindows();
}

3. 使用 Keyboards

对于给定的WebClient ,在任何时候焦点定在一个元素上,没有必要把焦点定在WebClient 里面的任意元素上。这里有几种方法,可以将焦点从一个元素移动到另一个元素上。最简单的方法就是调用HtmlPage.setFocusedElement(HtmlElement),这种方法将会把焦点从任何获得焦点的元素移动到指定的新组件上,沿途将会触发已经定义的所有的 onfocus和 onblur 方法。
调用HtmlPage.getFocusedElement() 可以确定当前获得焦点的元素。通过tab 键模拟键盘导航,你可以调用HtmlPage.tabToNextElement() 和HtmlPage.tabToPreviousElement() ,通过定义的tab顺序循环向前或向后。这个tab 顺序可以通过在很多元素的tabindex属性定义,想HTML 规范那样。
HtmlPage.getTabbableElements()方法返回所有可标签化的元素已定义的顺序的列表,可以通过此方法查询已定义的tab 顺序。
快捷键可以调用键盘的助记符,其可以方法HtmlPage.pressAccessKey(char)模拟。为了使用特殊的键,你可以使用htmlElement.type(int)方法,参数为KeyboardEvent.DOM_VK_PAGE_DOWN。
最后需要断言每一个可标签化的元素都定义了tabindex属性,可以通过WebAssert.assertAllTabIndexAttributesSet()实现。

4.使用Table

简单表格例子

第一组简单的例子将会是用下面的html文件

<html><head><title>Tablesampletitle>head><body>
          <table id="table1">
            <tr>
               <th>Numberth>
               <th>Descriptionth>
            tr>
            <tr>
               <td>5td>
               <td>Bicycletd>
            tr>
          table>
       body>html>

下面这个例子将展示所有的行和单元格是如何迭代的

finalHtmlTable table = page.getHtmlElementById("table1");
       for(final HtmlTableRow row : table.getRows()) {
          System.out.println("Found row");
          for (final HtmlTableCell cell :row.getCells()) {
            System.out.println("   Found cell: " + cell.asText());
          }
       }

下面这个例子将会展示如何访问指定的行和列

       final WebClient webClient = new WebClient();
       finalHtmlPage page = webClient.getPage("http://foo.com");
       //通过id获取表格
       finalHtmlTable table = page.getHtmlElementById("table1");
       //打印第一行第二列
       System.out.println("Cell(1,2)=" + table.getCellAt(1,2));

复杂表格例子

这一组例子将会使用更复杂的表格,表格包括表头、脚注和主体以及一个标题。

<html><head><title>Tablesampletitle>head><body>
          <table id="table1">
            <caption>My complextablecaption>
            <thead>
               <tr>
                   <th>Numberth>
                   <th>Descriptionth>
               tr>
             thead>
            <tfoot>
               <tr>
                   <td>7td>
                   <td>td>
               tr>
            tfoot>
            <tbody>
               <tr>
                   <td>5td>
                   <td>Bicycletd>
               tr>
            tbody>
            <tbody>
               <tr>
                   <td>2td>
                   <td>Tricycletd>
               tr>
            tbody>
          table>
       body>html>

HtmlTableHeader,HtmlTableFooter和HtmlTableBody部分是以行分组的。其最多只能有一个头和一个页脚,但可能会有不止一个的身体。行中包含的都可以通过getRows()访问。

       final HtmlTableHeader header = table.getHeader();
       final List headerRows = header.getRows();
       final HtmlTableFooter footer = table.getFooter();
       final List footerRows = footer.getRows();
       for(final HtmlTableBody body : table.getBodies()) {
          final List rows =body.getRows();
          ...
       }

每个表格可以选择性的有一个标题,用于说明
final String caption = table.getCaptionText();

5.使用Frames

例一

可以通过HtmlPage.getFrames()获取页面里面的或