HtmlUnit:自动化操作web页面的java工具

java有httpclient等工具,可以模拟进行一些web操作,但一些逻辑是在前端js中执行的,此时httpclient就比较困难了。

此时可以考虑使用HtmlUnit,模拟出一个浏览器,全程在浏览器中操作。

 

本文以 在百度中输入搜索关键字->点击“百度一下” 按钮->打印搜索结果 这一过程为例,演示HtmlUnit的使用

 

首先,我们要把上面的过程再代码化一点,F12打开开发者工具,检查发现输入框的id是kw,查询按钮的id是su。

而点击查询后,查询结果是写在这样的div里:

<div  data-tools="{'title': &quot;xxx技术博客_51CTO博客&quot;,'url': xxx;}" aria-hidden="true"></div>

 

因此,上述过程可以描述为

1、打开百度首页

2、查找id为kw的元素,写入查询关键字

3、查找id为su的元素,点击它

4、在页面中查找div标签并打印data-tools属性。

 

依照此过程,我们就开始写代码了:

引入maven依赖

        <dependency>
            <groupId>net.sourceforge.htmlunit</groupId>
            <artifactId>htmlunit</artifactId>
            <version>2.60.0</version>
        </dependency>

按流程写代码

package org.example;

import com.gargoylesoftware.htmlunit.BrowserVersion;
import com.gargoylesoftware.htmlunit.NicelyResynchronizingAjaxController;
import com.gargoylesoftware.htmlunit.WebClient;
import com.gargoylesoftware.htmlunit.html.DomElement;
import com.gargoylesoftware.htmlunit.html.HtmlPage;
import com.gargoylesoftware.htmlunit.html.HtmlSubmitInput;
import com.gargoylesoftware.htmlunit.html.HtmlTextInput;
import com.gargoylesoftware.htmlunit.util.Cookie;
import org.apache.commons.lang3.StringUtils;

import java.util.LinkedList;
import java.util.List;
import java.util.Set;

public class Main {
    public static void main(String[] args) {
        // 创建一个模拟 Chrome 浏览器的 WebClient 实例
        final WebClient webClient = new WebClient(BrowserVersion.CHROME);

        // 配置 WebClient
        webClient.getOptions().setThrowExceptionOnScriptError(false);//当JS执行出错的时候是否抛出异常, 这里选择不需要
        webClient.getOptions().setThrowExceptionOnFailingStatusCode(false);//当HTTP的状态非200时是否抛出异常, 这里选择不需要
        webClient.getOptions().setActiveXNative(false);
        webClient.getOptions().setCssEnabled(false);//是否启用CSS, 因为不需要展现页面, 所以不需要启用
        webClient.getOptions().setJavaScriptEnabled(true); //很重要,启用JS
        webClient.setAjaxController(new NicelyResynchronizingAjaxController());//很重要,设置支持AJAX

        HtmlPage page = null;
        try {
            // 访问百度主页
            page = webClient.getPage("https://www.baidu.com/");


            // 找到搜索输入框
            HtmlTextInput textField;
            do {
                textField = (HtmlTextInput) page.getElementById("kw");
                if (null != textField) {
                    break;
                }
                // 未找到说明页面还没加载完,继续等待页面加载完成
                webClient.waitForBackgroundJavaScript(1000);
            } while (true);

            // 输入查询文本
            textField.setValueAttribute("HtmlUnit自动测试");
            // 找到提交按钮并点击
            HtmlSubmitInput button = (HtmlSubmitInput) page.getElementById("su");
            page = button.click();

            //解析页面结果 这里如果百度的页面改了,需要做相应的调整
            List<String> res = new LinkedList<>();
            do {
                // 等待异步 JS 执行完成
                webClient.waitForBackgroundJavaScript(1000);
                // 提取结果页面中的<div data-tools="{'title': xxx">元素,也就是百度的检索结果关键元素
                for (DomElement div : page.getElementsByTagName("div")) {
                    String text = div.getAttribute("data-tools");
                    if (StringUtils.isNotBlank(text)) {
                        res.add(text);
                    }
                }
            } while (res.isEmpty());//res非空说明解析到结果了

            for (String s : res) {
                System.out.println(s);
            }


            System.out.println("--------------------------------------------------");
            // 获取并打印 cookies
            Set<Cookie> cookies = webClient.getCookieManager().getCookies();
            System.out.println("Cookies:");
            for (Cookie cookie : cookies) {
                System.out.println("Name: " + cookie.getName() + ", Value: " + cookie.getValue());
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            webClient.close();
        }
    }


}

运行得到结果。

 

最后提醒,本文只是以此为例介绍HtmlUnit的使用,请读者在应用中注意遵纪守法,各网站基本都有反爬虫机制,爬虫写得好,牢饭吃到饱。HtmlUnit更应该用到页面自动化测试等场景,而不是打擦边球去写爬虫。

posted @   懒惰芜菁  阅读(168)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 从HTTP原因短语缺失研究HTTP/2和HTTP/3的设计差异
· 三行代码完成国际化适配,妙~啊~
点击右上角即可分享
微信分享提示