java有httpclient等工具,可以模拟进行一些web操作,但一些逻辑是在前端js中执行的,此时httpclient就比较困难了。
此时可以考虑使用HtmlUnit,模拟出一个浏览器,全程在浏览器中操作。
本文以 在百度中输入搜索关键字->点击“百度一下” 按钮->打印搜索结果 这一过程为例,演示HtmlUnit的使用
首先,我们要把上面的过程再代码化一点,F12打开开发者工具,检查发现输入框的id是kw,查询按钮的id是su。
而点击查询后,查询结果是写在这样的div里:
<div data-tools="{'title': "xxx技术博客_51CTO博客",'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更应该用到页面自动化测试等场景,而不是打擦边球去写爬虫。
标签:web,java,htmlunit,gargoylesoftware,import,页面,com,webClient,HtmlUnit From: https://www.cnblogs.com/imliuyu/p/18374846