Java:爬虫htmlunit

为什么htmlunit与HttpClient两者都可以爬虫、网页采集、通过网页自动写入数据,我们会推荐使用htmlunit呢?

一、网页的模拟化

首先说说HtmlUnit相对于HttpClient的最明显的一个好处,HtmlUnit更好的将一个网页封装成了一个对象,如果你非要说HttpClient返回的接口HttpResponse实际上也是存储了一个对象那也可以,但是HtmlUnit不仅保存了这个网页对象,更难能可贵的是它还存有这个网页的所有基本操作甚至事件。这就是说,我们对于操作这个网页可以像在jsp中写js一样,这是非常方便的,比如:你想某个节点的上一个节点,查找所有的按钮,查找样式为"bt-style"的所有元素,对于某些元素先进行一些改造,然后再转成String,或者我直接得到这个网页之后操作这个网页,完成一次提交都是非常方便的。这意味着你如果想分析一个网页会来的非常的容易

二、网络响应的自动化处理

HtmlUnit拥有强大的响应处理机制,我们知道:常见的404是找不到资源,100等是继续,300等是跳转...我们在使用HttpClient的时候它会把响应结果告诉我们,当然,你可以自己来判断,比如说,你发现响应码是302的时候,你就在响应头去找到新的地址并自动再跳过去,发现是100的时候就再发一次请求,你如果使用HttpClient,你可以这么去做,也可以写的比较完善,但是,HtmlUnit已经较为完整的实现了这一功能,甚至说,他还包括了页面JS的自动跳转(响应码是200,但是响应的页面就是一个JS)

三、并行控制 和串行控制

既然HtmlUnit封装了那么多的底层api和hHttpClient操作,那么它有没有给我们提供自定义各种响应策略和监听整个执行过程的方法呢?,答案是肯定的。由于HtmlUnit提供的监听和控制方法比较多,我说几个大家可能接触比较少,但很有用的方法。其他的类似于:设置CSS有效,设置不抛出JS异常,设置使用SSL安全链接,诸如此类,大家通过webClient.getOptions().set***,就可以设置了,这种大家都比较熟了。

四、强大的缓存机制

为什么第一次获取一个网页可能会比较慢,但是第二次来拿就特别快呢?在HtmlUnit源码webClient类中的loadWebResponseFromWebConnection方法中我们可以看到。

以下简单介绍下如何去分析网页及涉及的代码:

其中url可以直接浏览器访问地址直接解析页面,也可以通过分析页面请求接口(开启google浏览器F12开发者模式,刷新对应页面即可查看请求数据地址 -- >> 具体数据需要通过分享查看)

引入maven包:

复制代码
<htmlunit.version>2.70.0</htmlunit.version>
<junit.version>4.13.2</junit.version>

<dependency>
    <groupId>net.sourceforge.htmlunit</groupId>
    <artifactId>htmlunit</artifactId>
    <version>${htmlunit.version}</version>
</dependency>
<dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>${junit.version}</version>
    <scope>test</scope>
</dependency>

@Slf4j
public class SpiderUtils {

	/**
	 * 获取http请求
	 *
	 * @param url
	 * @return
	 * @throws Exception
	 */
	public static String crawlPageApi(String url) throws Exception {
		// WebClient webClient = PooledClientFactory.getInstance().getClient();
		WebClient webClient = ThreadLocalClientFactory.getInstance().crawlPageApi();
		//抓取网页
		Page page = webClient.getPage(url);
		//打印当前线程名称及网页标题
		log.info(Thread.currentThread().getName() + " [ " + url + " ] : " + page.toString());
		WebResponse response = page.getWebResponse();
		String json = response.getContentAsString();
		log.info(Thread.currentThread().getName() + " [ " + json + " ] : ");
		return json;
	}

	/**
	 * 功能描述:抓取页面时并解析页面的js
	 *
	 * @param url
	 * @throws Exception
	 */
	public static HtmlPage crawlPageWithAnalyseJs(String url) throws Exception {
		WebClient webClient = ThreadLocalClientFactory.getInstance().crawlPageWithAnalyseJs();
		//抓取网页
		HtmlPage page = webClient.getPage(url);
		webClient.waitForBackgroundJavaScript(1000);
		//打印当前线程名称及网页标题
		System.out.println(Thread.currentThread().getName() + " [ " + url + " ] : " + page.getTitleText());
		return page;
	}

	/**
	 * 功能描述:抓取页面时不解析页面的js
	 *
	 * @param url
	 * @throws Exception
	 */
	public static HtmlPage crawlPageWithoutAnalyseJs(String url) throws Exception {
		WebClient webClient = ThreadLocalClientFactory.getInstance().crawlPageWithAnalyseJs();
		//抓取网页
		HtmlPage page = webClient.getPage(url);
		//打印当前线程名称及网页标题
		System.out.println(Thread.currentThread().getName() + " [ " + url + " ] : " + page.getTitleText());
		return page;
	}

}

目前来说,只是简单运用爬虫爬取抓取对应数据进行分析,具体的爬取规则需要根据实际情况来制定,数据量过大的时候还需要考虑通过读写分离,分库分表来解决效率问题

相关推荐
想学习java初学者6 小时前
SpringBoot整合Vertx-Mqtt多租户(优化版)
java·spring boot·后端
AC赳赳老秦6 小时前
政企内网落地:OpenClaw 离线环境深度适配方案,无外网场景下本地化模型对接与全功能使用
java·大数据·运维·python·自动化·deepseek·openclaw
weixin_449173656 小时前
在 Java 中,‌线程安全的 List‌ 主要有以下几种实现方式,它们的效率取决于具体的使用场景(尤其是读写比例):
java·线程安全的list
砚底藏山河6 小时前
股票数据API接口:如何获取股票历历史分时KDJ数据
java·python·maven
科技牛牛7 小时前
AI爬虫引爆代理IP产业:一场正在发生的数据粮草争夺战
人工智能·爬虫·tcp/ip·数据安全·ip地址查询
小白学大数据7 小时前
JS 混淆加密下的 Python 爬虫解决方案
javascript·爬虫·python
MegaDataFlowers7 小时前
运行若依项目
java
lulu12165440788 小时前
JetBrains IDE 终极AI编程方案:CC GUI插件让Claude Code和Codex丝滑运行
java·ide·人工智能·python·ai编程
('-')8 小时前
八股复习2:Java Array list和Linked list
java·开发语言
逸Y 仙X9 小时前
Elasticsearch时间类型实战
java·大数据·elasticsearch·搜索引擎·全文检索