【Java-Crawler】爬取动态页面(HtmlUnit、WebMagic)

news/2024/11/19 18:40:38/

爬取动态页面(WebMagic、HtmlUnit)

  • 一、HtmlUnit的基本使用
    • 引入依赖
    • 一般使用步骤
    • WebClient 的一些配置(上述一般步骤中的第二步)
  • 二、案例(爬取CSDN首页)测试(WebMagic+HtmlUnit)
  • 三、总结

上次提出了用 Selenium+浏览器驱动 去模拟浏览器的行为,然后去爬取动态页面(爬取动态页面(WebMagic、Selenium、ChromeDriver))。但是真的是太慢太慢了,而且 WebMagic 很多特性都用不了了,比如:多线程去处理请求、使用Pipeline去对结果集进行处理、请求去重…WebMagic最后被用成了HttpClient、Jsoup,失去了框架的意义。(也有可能是小编没合理地去模块化,但慢是真慢)

所以这里提出一个简单易用的工具——HtmlUnit,它可以模拟浏览器的行为,支持JavaScript解析和执行,可以用于解析动态页面。但它解析JavaScript的时候也是比较慢的,但后续用 WebMagic 去处理静态页面就快起来了。就比如说处理某网站的主页(动态页面)是需要解析JavaScript的,但主页里面的超链接对应的网页是静态网页,这时就可以直接用WebMagic去处理就可以了,速度就有了。

这里得说明一下 HtmlUnit 的缺点,方便后面讲解其使用:

  • 不支持所有的动态页面:虽然 HTMLUnit 可以处理 JavaScript 和 AJAX,但是它并不支持所有的动态页面。一些高度复杂的动态页面可能会导致 HTMLUnit 无法正确解析页面。(比如:51job)
  • 缺乏可视化界面:HTMLUnit 是一个 GUI-less浏览器,因此它缺乏可视化界面,这使得它不太适合用于测试和调试 Web 应用程序。(但咱这用的是去爬虫,所以问题应该不大)
  • 对JavaScript的支持并不完美:HTMLUnit 的 JavaScript 引擎不如一些主流浏览器的 JavaScript 引擎强大,所以当用 HtmlUnit 去解析的时候,可能会出现一些JavaScript的问题。(这个根据调试结果,自己应该做相应的调整选择)

一、HtmlUnit的基本使用

引入依赖

需要 htmlunit 依赖和 commons-io 这个工具依赖。

        <dependency><groupId>commons-io</groupId><artifactId>commons-io</artifactId><version>2.11.0</version></dependency><dependency><groupId>net.sourceforge.htmlunit</groupId><artifactId>htmlunit</artifactId><version>2.70.0</version></dependency>

一般使用步骤

// 1. 创建 WebClient 对象,模拟浏览器行为
WebClient client = new WebClient();
// 2. 对 client 进行一些配置
// 比如设置不需要解析css时
client.getOptions().setCssEnabled(false);
// 3. 打开网页(通过getPage(url)方法),该过程进行了解析
HtmlPage htmlPage = client.getPage(url);
// 4. 因为小编一般用它就是解析动态页面的,所以一般都是会解析JavaScript的
// 所以这里最好设一个解析script时间,让它充分得以解析
client.waitForBackgroundJavaScript(10*1000);// 10s
// 5. 获取解析后的页面html源代码字符串
String htmlStr = htmlPage.asXml();
// 6. 再利用webmagic中的Html类去构造Html对象去处理数据
Html html = new Html(htmlStr);
// 7. 关闭WebClient
client.close();

WebClient 的一些配置(上述一般步骤中的第二步)

  1. 开启JavaScript解析(默认是开启的)
client.getOptions().setJavaScriptEnabled(true);
  1. 关闭CSS解析(默认是开启的)
client.getOptions().setCssEnabled(false);
  1. 禁止抛出JavaScript错误,防止程序终止(默认是开启的)
client.getOptions().setThrowExceptionOnScriptError(false);
  1. 等待JavaScript执行完成(这个设在getPage方法后,对面上面的第四步)
client.waitForBackgroundJavaScript(10*1000);// 10s
  1. 设置浏览器的 User-Agent,反反爬虫策略之一。让浏览器觉得你不是爬虫用户访问的。
client.addRequestHeader("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.3");

二、案例(爬取CSDN首页)测试(WebMagic+HtmlUnit)

爬取CSDN首页,案例代码

@Component
public class TestProcessor implements PageProcessor {@SneakyThrows@Overridepublic void process(Page page) {if(page.getUrl().toString().equals(url)) {// 创建WebClient对象WebClient client = new WebClient();// 开启自动解析JavaScriptclient.getOptions().setJavaScriptEnabled(true);client.getOptions().setCssEnabled(false);client.getOptions().setThrowExceptionOnScriptError(false);// 打开网页,获取HtmlPage对象HtmlPage htmlPage = client.getPage(page.getUrl().toString());client.waitForBackgroundJavaScript(30000);// 页面源代码String s = htmlPage.asXml();Html html = new Html(s);// 获取当页职位urlList<String> allUrl = html.css("html body div#app div div.main div.page-container.page-component div div.home_wrap div#floor-blog-index_747 div.floor-blog-index div.blog-content div.Community div.active-blog div.Community-item-active.blog div.Community-item.blog div.content a.blog","href").all();// 去获取数据、处理数据、保存数据for (String jurl : allUrl) {page.addTargetRequest(jurl);// 静态页面交给webmagic处理}client.close();}else{addSave(page);}}private void addSave(Page page) {// 获取对应的html对象Html jobHtml = page.getHtml();// 获取数据并保存数据// 存入数据库}private Site site = Site.me().setRetryTimes(3).setSleepTime(1000).setTimeOut(3000).setUserAgent("Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.3");@Overridepublic Site getSite() {return this.site;}// initialDelay 当任务启动后,等待多久执行方法// fixedDelay 每隔多久执行这个方法@Scheduled(initialDelay = 1000,fixedDelay = 100000)public void process(){Spider.create(new TestProcessor()).addUrl(url).thread(5).run();}private String url = "https://blog.csdn.net/?spm=1001.2101.3001.4477";
}

测试效果

首页JavaScript被解析后的 CSDN HTML 代码

在这里插入图片描述

首页博客超链接对应的博客网页(它是静态网页),其 HTML 代码解析如下图所示

在这里插入图片描述

三、总结

使用 HtmlUnit 去解析动态页面然后去爬虫是比较方便的,这是由于 HtmlUnit 工具易用的原因。但由于它存在 JavaScript 支持并不完美,外加有些动态页面它也是解析不了的缺陷,使用 Selenium+浏览器驱动 这种方式也不能说就比 HtmlUnit 解析要差。

爬虫使用’工具’总结就是:

  • 静态页面直接用 Webmagic;
  • 动态页面如果可以用 HtmlUnit 就用 HtmlUnit;
  • HtmlUnit 完成不了的再用 Selenium+浏览器驱动。

还有就是小编发现很多网站首页是动态页面的,但动态网页里超链接对应的页面一般是静态网页的。(小编没说绝对哈,一般是这样的)


http://www.ppmy.cn/news/89156.html

相关文章

《微服务实战》 第十五章 RabbitMQ 延迟队列

前言 实际业务中&#xff0c;例如秒杀系统&#xff0c;秒杀商品成功会有截止时间&#xff0c;这时需要用到RabbitMQ延迟服务。 1、RabbitMQ延迟队列 1.1、方式1&#xff1a;RabbitMQ通过死信机制来实现延迟队列的功能 TTL &#xff0c;即 Time-To-Live&#xff0c;存活时间…

Maven 概述及下载安装

一、为什么要学习 Maven 我们构建一个项目需要用到很多第三方的类库&#xff0c;就需要引入大量的jar包&#xff0c;并且Jar包之间的关系错综复杂&#xff0c;缺少任何一个Jar包都会导致项目编译失败。Maven 能帮助我们下载及管理依赖。 本地项目代码开发完成后&#xff0c;我…

CMake初学笔记(一)

CMake初学笔记&#xff08;一&#xff09; CMake是什么CMake怎么实现跨平台CMake具体实践过程CMakeLists.txt编写快速入门常见函数例子 CMake是什么 跨平台编译工具&#xff0c;为了实现“write once, run everywhere”。 CMake怎么实现跨平台 开发者编写与平台无关的编译过…

【小沐学NLP】Python实现聊天机器人(OpenAI,模型概述笔记)

&#x1f37a;NLP开发系列相关文章编写如下&#x1f37a;&#xff1a;1&#x1f388;【小沐学NLP】Python实现词云图&#x1f388;2&#x1f388;【小沐学NLP】Python实现图片文字识别&#x1f388;3&#x1f388;【小沐学NLP】Python实现中文、英文分词&#x1f388;4&#x1…

Seata AT模式源码解析三(AT模式工作机制)

文章目录 代码示例流程源码解析开启全局事务注册分支事务一阶段提交全局事务提交分支事务二阶段提交全局事务回滚分支事务二阶段回滚 代码示例 从一个微服务示例开始&#xff0c;案例采用Seata官方提供的Demo。 用户购买商品的业务逻辑。整个业务逻辑由3个微服务提供支持&…

Bits, Bytes and Integers——二进制unsigned以及Two-complement表示,十六进制

这篇文章梳理一下Bits, Bytes and Integers——二进制unsigned以及Two-complement表示&#xff0c;十六进制这些事儿。 计算机中所有数据都是用二进制的0和1组成的&#xff0c;直接上知识点。 二进制 Unsigned以及Two-complement 同样的一串二进制数&#xff0c;按照有符号…

0基础学习VR全景平台篇第31章:场景功能-嵌入图片

大家好&#xff0c;欢迎收看蛙色平台免费教程&#xff01; 功能位置示意 一、本功能将用在哪里&#xff1f; 嵌入功能可对VR全景作品嵌入【图片】【视频】【文字】【标尺】四种不同类型内容&#xff0c;本次主要带来图片类型的介绍&#xff0c;满足场景营销、重点标注、幻灯片…

docker移动默认地址

停止 Docker 服务&#xff1a;首先&#xff0c;停止正在运行的 Docker 服务。在 Linux 系统上&#xff0c;可以使用以下命令停止 Docker 服务&#xff1a; sudo systemctl stop docker 在 Windows 上&#xff0c;可以通过 Docker Desktop 的系统托盘图标或者任务管理器停止 Do…