文档章节

htmlunit 入门--官网示例

诺岚
 诺岚
发布于 2017/08/30 08:26
字数 2270
阅读 54
收藏 0

官网:http://htmlunit.sourceforge.net/

HtmlUnit是一个“GUI程序的GUI-less浏览器”。它模拟HTML文档,并提供一个API,允许您调用页面,填写表单,点击链接等,就像您在“正常”浏览器中所做的一样。

它具有相当好的JavaScript支持(它不断改进),并且能够使用相当复杂的AJAX库来工作,根据所使用的配置模拟Chrome,Firefox或Internet Explorer。

它通常用于测试目的或从网站检索信息。

介绍

依赖性页面列出了你需要在你的classpath中所有罐子。

com.gargoylesoftware.htmlunit.WebClient类是主要的起点。这将模拟一个Web浏览器,并将用于执行所有的测试。

大多数单元测试将在像JUnit 这样的框架中完成,所以这里的所有示例都将假设我们正在使用它。

在第一个示例中,我们创建了Web客户端,并从HtmlUnit网站加载了主页。然后我们验证此页面是否具有正确的标题。请注意,getPage()可以根据返回的数据的内容类型返回不同类型的页面。在这种情况下,我们期待一种内容类型的text/html,所以我们将结果转换为一个com.gargoylesoftware.htmlunit.html.HtmlPage。

    @Test
    public void homePage() throws Exception {
        //实例化webClent 对象
        WebClient webClient = new WebClient();
        //获取页面
        HtmlPage page = webClient.getPage("http://htmlunit.sourceforge.net");
        //返回此页面的标题或如果指定的标题不是一个空字符串。
        System.out.println("获取的标题是: 与" + page.getTitleText());
        //获取网页中的内容,以XML方法返回
        //返回一个字符串表示XML文档的元素和所有它的孩子(递归)。是当前页面编码使用的字符集。
        String pageAsXml = page.asXml();
        //contains 包含
        System.out.println(pageAsXml.contains("<body class=\"composite\">"));
        //获取网页中的内容以文本方式返回
        //返回一个代表该元素的文本表示会对用户可见的如果这个页面是显示在一个web浏览器。例如,single-selection选择元素将返回当前选中的值为文本。

        String pageAsText = page.asText();
        //是否包含以下内容
        System.out.println(pageAsText.contains("Support for the HTTP and HTTPS protocols"));


    }

模仿一个特定的浏览器

通常你会想要模拟一个特定的浏览器。这通过将com.gargoylesoftware.htmlunit.BrowserVersion传递到WebClient构造函数来完成。为一些常见的浏览器提供常量,但您可以通过实例化BrowserVersion创建自己的特定版本。

    @Test
    public void homePage_Firefox() throws Exception {
        //实例化webClent 对象,并设定指定的浏览器
        WebClient webClient = new WebClient(BrowserVersion.FIREFOX_52);
        HtmlPage page = webClient.getPage("http://htmlunit.sourceforge.net");
        //返回此页面的标题或如果指定的标题不是一个空字符串。
        System.out.println("HtmlUnit - Welcome to HtmlUnit" + page.getTitleText());


    }

指定此BrowserVersion将更改发送到服务器的用户代理头,并将更改某些JavaScript的行为。

寻找一个特定的元素

一旦你引用了一个HtmlPage,你可以通过'get'方法之一,或使用XPath来搜索一个特定的HtmlElement。

以下是通过ID查找“div”的示例,并按名称获取锚点:

@Test
public void getElements() throws Exception {
    try (final WebClient webClient = new WebClient()) {
        final HtmlPage page = webClient.getPage("http://some_url");
        final HtmlDivision div = page.getHtmlElementById("some_div_id");
        final HtmlAnchor anchor = page.getAnchorByName("anchor_name");
    }
}

查找元素的简单方法可能是查找特定类型的所有元素。

//获取指定的元素
    @Test
    public void getElements() throws Exception {
        //实例化webClient 对象
        WebClient webClient = new WebClient();
        //执行get方法,获取网页
        HtmlPage page = webClient.getPage("http://htmlunit.sourceforge.net");
        //根据指定ID搜索
        HtmlDivision div = page.getHtmlElementById("banner");
        //根据指定名称搜索
        HtmlAnchor anchor = page.getAnchorByName("HtmlUnit");
        System.out.println(page.toString());
        System.out.println("-------------------------");
        System.out.println(anchor.toString());
    }

XPath是更复杂的搜索的建议方法,可以在W3Schools中找到一个简短的教程 

    @Test
    public void xpath() throws Exception {
        WebClient webClient = new WebClient();
        HtmlPage page = webClient.getPage("http://htmlunit.sourceforge.net");

        //得到的所有div的列表
        List<?> divs = page.getByXPath("//div");
        for (Object div : divs) {
            System.out.println(div.toString());

        }
        //获取div
        List<Object> xPath = page.getByXPath("/html/body/div[1]/div[3]");
        for (Object o : xPath) {
            System.out.println("-------------------");
            System.out.println(o.toString());
        }
    }

您也可以使用CSS选择器

    @Test
    public void xpath2() throws Exception {
        WebClient webClient = new WebClient();
        HtmlPage page = webClient.getPage("http://htmlunit.sourceforge.net");

        //得到的所有div的列表
        DomNodeList<DomNode> divs = page.querySelectorAll("div");
        for (DomNode div : divs) {
            //输出搜索到的div
            System.out.println(div.toString());
        }

        //获取div的id为'breadcrumbs'
        DomNode div = page.querySelector("div#breadcrumbs");
        System.out.println("--------------------");
        System.out.println(div.toString());
    }

使用代理服务器

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

    @Test
    public void homePage_proxy() throws Exception {
        //代理IP地址
        String myproxyserver = "";
        //代理IP端口号
        int myProxyPort = 80;
        WebClient webClient = new WebClient(BrowserVersion.FIREFOX_52, "myproxyserver", myProxyPort);
        //代理设置用户名和密码
        DefaultCredentialsProvider credentialsProvider = (DefaultCredentialsProvider) webClient.getCredentialsProvider();
        credentialsProvider.addCredentials("username", "password");

        HtmlPage page = webClient.getPage("http://htmlunit.sourceforge.net");
        System.out.println("HtmlUnit - Welcome to HtmlUnit" + page.getTitleText());
    }

指定此BrowserVersion将更改发送到服务器的用户代理头,并将更改某些JavaScript的行为。

提交表单

通常我们要更改表单中的值并将表单提交回服务器。以下示例显示了如何执行此操作。


    @Test
    public void submittingForm() throws Exception {
        WebClient webClient = new WebClient();

        // 得到第一页
        HtmlPage page1 = webClient.getPage("http://some_url");

        // 我们正在处理的形式,在这种形式,
        // 找到submit按钮,我们想改变的。
        HtmlForm form = page1.getFormByName("myform");
        HtmlSubmitInput button = form.getInputByName("submitbutton");
        HtmlTextInput textField = form.getInputByName("userid");

        // 改变文本框的值
        textField.setValueAttribute("root");

        // 现在提交表单通过单击按钮,回到第二页。
        final HtmlPage page2 = button.click();

    }

使用键盘:

    

对于给定的WebClient,在任何给定的时间,焦点最多可以在一个元素上。Focus不必在WebClient中的任何元素上。

将焦点从一个元素移动到另一个元素有几种方法。最简单的是调用HtmlPage.setFocusedElement(HtmlElement)。此方法将从当前拥有的任何元素(如果有)中删除焦点,并将其设置为新组件。一路上,它将触发已定义的任何“onfocus”和“onblur”处理程序。

当前拥有焦点的元素可以通过调用HtmlPage.getFocusedElement()来确定。

要通过选项卡键模拟键盘导航,您可以调用HtmlPage.tabToNextElement()和HtmlPage.tabToPreviousElement()通过定义的选项卡顺序向前或向后循环。此标签顺序 由HTML规范定义的各种元素上的tabindex属性定义。您可以使用方法HtmlPage.getTabbableElements()查询定义的选项卡顺序,该方法将以定义的Tab顺序返回所有可选元素的列表。

访问键,通常称为键盘助记符,可以使用方法HtmlPage.pressAccessKey(char)进行模拟。

要使用特殊键,可以使用htmlElement.type(int)与KeyboardEvent.DOM_VK_PAGE_DOWN。

最后,有一个测试的断言,将验证每个tabbable元素都有一个定义的tabindex属性。这是通过WebAssert.assertAllTabIndexAttributesSet()完成的。

以下代码为软件中全选复制出来:

POM.XML

<dependencies>
    <!-- https://mvnrepository.com/artifact/net.sourceforge.htmlunit/htmlunit -->
    <dependency>
        <groupId>net.sourceforge.htmlunit</groupId>
        <artifactId>htmlunit</artifactId>
        <version>2.27</version>
    </dependency>
    <!-- https://mvnrepository.com/artifact/junit/junit -->
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.12</version>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>org.junit.jupiter</groupId>
        <artifactId>junit-jupiter-api</artifactId>
        <version>RELEASE</version>
    </dependency>

</dependencies>

import com.gargoylesoftware.htmlunit.BrowserVersion;
import com.gargoylesoftware.htmlunit.DefaultCredentialsProvider;
import com.gargoylesoftware.htmlunit.WebClient;
import com.gargoylesoftware.htmlunit.html.*;
import org.junit.jupiter.api.Test;


import java.util.List;

public class htmlunit {
    @Test
    public void homePage() throws Exception {
        //实例化webClent 对象
        WebClient webClient = new WebClient();
        //获取页面
        HtmlPage page = webClient.getPage("http://htmlunit.sourceforge.net");
        //返回此页面的标题或如果指定的标题不是一个空字符串。
        System.out.println("获取的标题是: 与" + page.getTitleText());
        //获取网页中的内容,以XML方法返回
        //返回一个字符串表示XML文档的元素和所有它的孩子(递归)。是当前页面编码使用的字符集。
        String pageAsXml = page.asXml();
        //contains 包含
        System.out.println(pageAsXml.contains("<body class=\"composite\">"));
        //获取网页中的内容以文本方式返回
        //返回一个代表该元素的文本表示会对用户可见的如果这个页面是显示在一个web浏览器。例如,single-selection选择元素将返回当前选中的值为文本。

        String pageAsText = page.asText();
        //是否包含以下内容
        System.out.println(pageAsText.contains("Support for the HTTP and HTTPS protocols"));


    }

    @Test
    public void homePage_Firefox() throws Exception {
        //实例化webClent 对象,并设定指定的浏览器
        WebClient webClient = new WebClient(BrowserVersion.FIREFOX_52);
        HtmlPage page = webClient.getPage("http://htmlunit.sourceforge.net");
        //返回此页面的标题或如果指定的标题不是一个空字符串。
        System.out.println("HtmlUnit - Welcome to HtmlUnit" + page.getTitleText());


    }

    //获取指定的元素
    @Test
    public void getElements() throws Exception {
        //实例化webClient 对象
        WebClient webClient = new WebClient();
        //执行get方法,获取网页
        HtmlPage page = webClient.getPage("http://htmlunit.sourceforge.net");
        //根据指定ID搜索
        HtmlDivision div = page.getHtmlElementById("banner");
        //根据指定名称搜索
        HtmlAnchor anchor = page.getAnchorByName("HtmlUnit");
        System.out.println(page.toString());
        System.out.println("-------------------------");
        System.out.println(anchor.toString());
    }


    @Test
    public void xpath() throws Exception {
        WebClient webClient = new WebClient();
        HtmlPage page = webClient.getPage("http://htmlunit.sourceforge.net");

        //得到的所有div的列表
        List<?> divs = page.getByXPath("//div");
        for (Object div : divs) {
            System.out.println(div.toString());

        }
        //获取div
        List<Object> xPath = page.getByXPath("/html/body/div[1]/div[3]");
        for (Object o : xPath) {
            System.out.println("-------------------");
            System.out.println(o.toString());
        }
    }

    @Test
    public void xpath2() throws Exception {
        WebClient webClient = new WebClient();
        HtmlPage page = webClient.getPage("http://htmlunit.sourceforge.net");

        //得到的所有div的列表
        DomNodeList<DomNode> divs = page.querySelectorAll("div");
        for (DomNode div : divs) {
            //输出搜索到的div
            System.out.println(div.toString());
        }

        //获取div的id为'breadcrumbs'
        DomNode div = page.querySelector("div#breadcrumbs");
        System.out.println("--------------------");
        System.out.println(div.toString());
    }

    @Test
    public void homePage_proxy() throws Exception {
        //代理IP地址
        String myproxyserver = "";
        //代理IP端口号
        int myProxyPort = 80;
        WebClient webClient = new WebClient(BrowserVersion.FIREFOX_52, "myproxyserver", myProxyPort);
        //代理设置用户名和密码
        DefaultCredentialsProvider credentialsProvider = (DefaultCredentialsProvider) webClient.getCredentialsProvider();
        credentialsProvider.addCredentials("username", "password");

        HtmlPage page = webClient.getPage("http://htmlunit.sourceforge.net");
        System.out.println("HtmlUnit - Welcome to HtmlUnit" + page.getTitleText());
    }

    @Test
    public void submittingForm() throws Exception {
        WebClient webClient = new WebClient();

        // 得到第一页
        HtmlPage page1 = webClient.getPage("http://some_url");

        // 我们正在处理的形式,在这种形式,
        // 找到submit按钮,我们想改变的。
        HtmlForm form = page1.getFormByName("myform");
        HtmlSubmitInput button = form.getInputByName("submitbutton");
        HtmlTextInput textField = form.getInputByName("userid");

        // 改变文本框的值
        textField.setValueAttribute("root");

        // 现在提交表单通过单击按钮,回到第二页。
        final HtmlPage page2 = button.click();

    }
}

 

© 著作权归作者所有

共有 人打赏支持
诺岚
粉丝 0
博文 101
码字总数 176372
作品 0
广州
程序员
HtmlUnit 网络爬虫 菜鸟的学习笔记(一)

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

木有芒果
2015/08/31
0
0
模拟浏览器的神器 - HtmlUnit

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

杨尚川
2014/04/04
0
6
Burp Xss Scanner插件开发思路分享(附下载)

  *本文原创作者:lufei,本文属FreeBuf原创奖励计划,未经许可禁止转载   0×00 前言   Burp虽然自带xss检测,但是Pyload与数量都不是自己能掌控的。所以自己写一款Xss检测插件,对一...

FreeBuf
05/12
0
0
使用Goodcrawler爬取700集的柯南

优酷在剧集太多时通过js生成剧集列表,而要获取其播放地址则需要点击来获取。gc使用htmlunit模拟了点击动作,可以轻易的获取全部播放地址。 以下是优酷动漫的配置: <?xml version="1.0" en...

shenbaise
2014/01/14
0
3
HtmlUnit 网络爬虫 菜鸟的学习笔记(二)

这次我以爬新浪微博为例,这个过程太纠结了,参考了好多大神的帖子,不过还是遗留了很多问题,我们慢慢来看,希望大神帮于指正,我的方法暂时来说还是比较挫的 登陆问题 爬新浪微博首先要登陆...

木有芒果
2015/09/01
0
1

没有更多内容

加载失败,请刷新页面

加载更多

Bash脚本输入参数的使用

Bash脚本输入参数的使用 Bash脚本传入的参数,在脚本中以位置的形式进行访问,即 $n 。例如,$1 为执行脚本的第一个参数,$2 为执行脚本的第二个参数。另外Bash中还提供了一些其它的便捷操作...

小陶小陶
21分钟前
2
0
多线程场景下,触发OOM的线程是否会影响其他线程的工作

public static void main(String[] args) { Thread t1 = new Thread(new Runnable() { @Override public void run() { int i = 0;......

麦馍
25分钟前
2
0
模拟Dubbo的zookeeper一致性Hash发现

接之前一篇<手写zookeeper来模拟dubbo的注册/发现>,使用一致性Hash来进行查找需要寻找的服务. Hash处理接口 public interface HashFunc { public Long hash(Object key);} 一致性Has...

算法之名
36分钟前
13
0
#mysql50# not Exist

data 目录有中文名称,可能是复制的"复件...."

少年不搬砖老大徒伤悲
50分钟前
2
0
在yii2中,让你action参数支持POST数据的小方法

我们先来看一段代码 class RaController extends Controller { public $enableCsrfValidation = false; public function actionSay($username = '',$city = ''){ echo "{$......

阿北2017
59分钟前
5
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部