Java:爬虫htmlunit

news/2024/7/19 12:12:29 标签: java, 爬虫

为什么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;
	}

}

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


http://www.niftyadmin.cn/n/5308411.html

相关文章

openssl ans1定义的实体

由于openssl中的ASN1的结构是通过宏来定义的&#xff0c;导致我们经常找不到他的结构在哪里&#xff0c;通过阅读rfc&#xff0c;并且对照OPENSSL&#xff0c;发现OPENSSL中的结构基本是按照相关rfc中的名称&#xff0c;在openssl中进行搜索&#xff0c;就能找到具体的定义了。…

汽车标定技术(十六)--FETK如何帮助Aurix实现快速原型、标定测量功能(2)

目录 1.数据访问概述 1.1 标定访问 1.2 测量访问 1.2.1 DAP直接访问 1.2.2 Trace访问

Java运算符简单介绍

文章目录 1. 算术运算符2. 赋值运算符3. 比较&#xff08;关系&#xff09;运算符4. 逻辑运算符5. 位运算符6. 条件运算符&#xff08;三元运算符&#xff09;7. 运算符优先级 1. 算术运算符 &#xff1a;加法 int a 5; int b 3; int sum a b; // 结果为8-&#xff1a;减…

EtherCAT主站SOEM -- 14 --Qt-Soem通过界面采集从站IO进行显示

EtherCAT主站SOEM -- 14 --Qt-Soem通过界面采集从站IO进行显示 一 mainwindow.c 文件函数:1.1 自定义PDO配置1.2 主站初始化二 motrorcontrol.c 文件三 allvalue.h 文件该文档修改记录:总结一 mainwindow.c 文件函数: 1.1 自定义PDO配置 int IO_setup(uint16 slave) {int

(PyTorch)TCN和RNN/LSTM/GRU结合实现时间序列预测

目录 I. 前言II. TCNIII. TCN-RNN/LSTM/GRU3.1 TCN-RNN3.2 TCN-LSTM3.3 TCN-GRU IV. 实验结果 I. 前言 前面已经写了一系列有关LSTM时间序列预测的文章&#xff1a; 深入理解PyTorch中LSTM的输入和输出&#xff08;从input输入到Linear输出&#xff09;PyTorch搭建LSTM实现时…

线性代数 --- 为什么LU分解中L矩阵的行列式一定等于正负1?

以下是关于下三角矩阵L的行列式一定等于-1的一些说明 笔者的一些话(写在最前面)&#xff1a; 这是一篇小文&#xff0c;是我写的关于求解矩阵行列式的一篇文章中的一部分。之所以把这一段专门提溜出来&#xff0c;是因为这一段相对于原文是可以完全独立的&#xff0c;也是因为我…

计算机毕业设计 SpringBoot的中小型制造企业质量管理系统 Javaweb项目 Java实战项目 前后端分离 文档报告 代码讲解 安装调试

&#x1f34a;作者&#xff1a;计算机编程-吉哥 &#x1f34a;简介&#xff1a;专业从事JavaWeb程序开发&#xff0c;微信小程序开发&#xff0c;定制化项目、 源码、代码讲解、文档撰写、ppt制作。做自己喜欢的事&#xff0c;生活就是快乐的。 &#x1f34a;心愿&#xff1a;点…

如何批量自定义视频画面尺寸

在视频制作和编辑过程中&#xff0c;对于视频画面尺寸的调整是一项常见的需求。有时候&#xff0c;为了适应不同的播放平台或满足特定的展示需求&#xff0c;我们需要对视频尺寸进行批量调整。那么&#xff0c;如何实现批量自定义视频画面尺寸呢&#xff1f;本文将为您揭示这一…