赞
踩
在当今信息爆炸的时代,网络数据的获取和处理变得至关重要。对于 Java 开发者而言,掌握高效的网页抓取技术是提升数据处理能力的关键。本文将深入探讨三款广受欢迎的 Java 网页抓取工具:Jsoup、HtmlUnit 和 WebMagic,分析它们的功能特点、优势以及适用场景,以助开发者选择最适合自己项目需求的工具。
Jsoup 是一款 Java 编写的开源 HTML 解析器,它提供了一套丰富的 API,用于解析、操作和清理 HTML 文档。Jsoup 能够从网页中提取数据,并且广泛应用于网络爬虫、数据挖掘和自动化测试等领域。
如果你使用的是 Maven,可以在 pom.xml 文件中添加以下依赖
<!-- https://mvnrepository.com/artifact/org.jsoup/jsoup -->
<dependency>
<groupId>org.jsoup</groupId>
<artifactId>jsoup</artifactId>
<version>1.17.2</version> <!-- 请使用最新版本 -->
</dependency>
以下是一个简单的 Jsoup 示例代码,演示了如何抓取百度首页上的热门搜索新闻:
public class JsoupExample {
public static void main(String[] args) {
// 目标网页 URL
String url = "https://www.baidu.com";
try {
// 连接到网页并获取文档对象
Document doc = Jsoup.connect(url).get();
// 获取百度首页热搜
Elements hotSearchList = doc.selectXpath("//*[@id=\"hotsearch-content-wrapper\"]/li");
System.out.println("今日百度热搜:");
// 遍历所有热搜新闻
for (Element hotSearch : hotSearchList) {
Elements newsMetaList = hotSearch.selectXpath(".//span");
for (Element newsMeta : newsMetaList) {
System.out.print(newsMeta.text() + " ");
}
System.out.print("\n");
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
运行结果截图如下:
Jsoup 主要用于静态网页的内容抓取,对于使用 Vue.js 等现代 JavaScript 框架构建的动态网站,其直接获取页面内容的能力受限。由于 Vue.js 等框架通过 JavaScript 动态生成页面内容,Jsoup 无法执行相应的脚本,因此可能无法获取到完整的、动态渲染的数据。
因此,使用 Jsoup 爬取这类网站时,通常只能获取到初始的、不包含动态数据的HTML结构。结果如下:
<!doctype html>
<html>
<head>
<meta charset="utf-8">
</head>
<body>
<div id="app"></div>
</body>
</html>
HtmlUnit 是一个用 Java 编写的无界面浏览器,它模拟 HTML 文档并提供了一系列 API,允许开发者以编程方式与网页进行交互。这个工具可以用于自动化测试、网络爬虫以及自动化网页交互等场景。HtmlUnit 支持 JavaScript(通过 Mozilla Rhino 引擎),并且能够处理 AJAX 功能,使得它能够与现代的动态网页进行交互。
如果你使用的是 Maven,可以在 pom.xml 文件中添加以下依赖
<!-- https://mvnrepository.com/artifact/org.htmlunit/htmlunit -->
<dependency>
<groupId>org.htmlunit</groupId>
<artifactId>htmlunit</artifactId>
<version>4.0.0</version> <!-- 请使用最新版本 -->
</dependency>
以下是一个简单的 HtmlUnit 示例代码,演示了如何抓取百度首页上的热门搜索新闻:
public class HtmlUnitExample {
public static void main(String[] args) {
// 目标网页 URL
String url = "https://www.baidu.com";
WebClient webClient = getWebClient();
try {
// 打开网页
HtmlPage page = webClient.getPage(url);
// 获取网页标题
String title = page.getTitleText();
System.out.println("网页标题: " + title);
// 获取百度首页热搜
List<DomElement> hotSearchList = page.getByXPath("//*[@id=\"hotsearch-content-wrapper\"]/li");
System.out.println("今日百度热搜:");
// 遍历所有热搜新闻
for (DomElement hotSearch : hotSearchList){
List<DomElement> newsMetaList = hotSearch.getByXPath(".//span");
for (DomElement newsMeta : newsMetaList) {
System.out.print(newsMeta.asNormalizedText() + " ");
}
System.out.print("\n");
}
} catch (Exception e) {
e.printStackTrace();
} finally {
// 关闭WebClient,释放资源
webClient.close();
}
}
/**
* <h2>获取一个 Web 模拟浏览器客户端</h2>
*/
public static WebClient getWebClient(){
// 浏览器设置
WebClient webClient = new WebClient(BrowserVersion.CHROME);
// ajax
webClient.setAjaxController(new NicelyResynchronizingAjaxController());
// 支持js
webClient.getOptions().setJavaScriptEnabled(true);
// 忽略js错误
webClient.getOptions().setThrowExceptionOnScriptError(false);
// 忽略css错误
webClient.setCssErrorHandler(new SilentCssErrorHandler());
// 不执行CSS渲染
webClient.getOptions().setCssEnabled(false);
// 超时时间
webClient.getOptions().setTimeout(3000);
// 允许重定向
webClient.getOptions().setRedirectEnabled(true);
// 允许cookie
webClient.getCookieManager().setCookiesEnabled(true);
return webClient;
}
}
运行结果截图如下:
WebMagic 是一个简单灵活的 Java 爬虫框架。基于 WebMagic,你可以快速开发出一个高效、易维护的爬虫。
WebMagic 总体架构图如下:
如果你使用的是 Maven,可以在 pom.xml 文件中添加以下依赖
<!-- https://mvnrepository.com/artifact/us.codecraft/webmagic-core -->
<!-- WebMagic是一个简单灵活的爬虫框架,其核心部分(webmagic-core)是一个精简的、模块化的爬虫实现。 -->
<dependency>
<groupId>us.codecraft</groupId>
<artifactId>webmagic-core</artifactId>
<version>0.9.0</version>
</dependency>
<!-- https://mvnrepository.com/artifact/us.codecraft/webmagic-extension -->
<!-- WebMagic的扩展模块(webmagic-extension)为使用者提供了更方便的编写爬虫的工具,包括注解格式定义爬虫、JSON、分布式等支持。 -->
<dependency>
<groupId>us.codecraft</groupId>
<artifactId>webmagic-extension</artifactId>
<version>0.9.0</version>
</dependency>
<!-- https://mvnrepository.com/artifact/us.codecraft/webmagic-selenium -->
<!-- WebMagic 是一个基于 Java 的开源网络爬虫框架,而 Selenium 是一个用于自动化 Web 浏览器的工具。 -->
<dependency>
<groupId>us.codecraft</groupId>
<artifactId>webmagic-selenium</artifactId>
<version>0.9.0</version>
</dependency>
以下是一个简单的 WebMagic 示例代码,演示了如何抓取百度首页上的热门搜索新闻:
1、自定义下载器
WebMagic-Selenium 是 WebMagic 爬虫框架的一个扩展,它结合了 WebMagic 的爬虫能力和 Selenium 的浏览器自动化功能。这种结合使得 WebMagic-Selenium 能够处理那些需要执行 JavaScript 或模拟用户交互才能获取完整信息的动态网页。
通过使用 WebMagic-Selenium,开发者可以利用 WebMagic 的简洁 API 来定义爬虫的抓取逻辑,同时使用 Selenium 来处理那些需要复杂交互的网页。例如,可以模拟用户的登录过程、处理弹出窗口、执行复杂的表单提交等操作。
WebMagic 默认使用了 Apache HttpClient 作为下载工具。
/**
* <h1>自定义下载器</h1>
* Downloader 负责从互联网上下载页面,以便后续处理。
* WebMagic 默认使用了Apache HttpClient作为下载工具。
* */
public class WNDownloader implements Downloader {
// 声明驱动
private RemoteWebDriver driver;
@Override
public Page download(Request request, Task task) {
// 第一个参数是使用哪种浏览器驱动,第二个参数是浏览器驱动的地址
System.setProperty("webdriver.chrome.driver",
"/Users/yaoshuaizhou/Downloads/chromedriver-mac-arm64/chromedriver");
// 创建浏览器参数对象
ChromeOptions chromeOptions = new ChromeOptions();
// 设置为 无界面浏览器 模式,若是不想看到浏览器打开,就可以配置此项
// chromeOptions.addArguments("--headless");
chromeOptions.addArguments("--window-size=1440,1080"); // 设置浏览器窗口打开大小
this.driver = new ChromeDriver(chromeOptions); // 创建驱动
driver.get(request.getUrl()); // 第一次打开url,跳转到登录页
try {
Thread.sleep(3000); // 等待打开浏览器
// 获取从process返回的site携带的cookies,填充后第二次打开url
Site site = task.getSite();
if (site.getCookies() != null) {
// for (Map.Entry cookieEntry : site.getCookies()
//
// .entrySet()) {
//
// Cookie cookie = new Cookie(cookieEntry.getKey(),
//
// cookieEntry.getValue());
//
// driver.manage().addCookie(cookie);
//
// }
// 添加对应domain的cookie后,第二次打开url
driver.get(request.getUrl());
}
Thread.sleep(2000);
// 需要滚动到页面的底部,获取完整的数据
driver.executeScript("window.scrollTo(0, document.body.scrollHeight - 1000)");
Thread.sleep(2000); // 等待滚动完成
// 获取页面,打包成Page对象,传给PageProcessor 实现类
Page page = createPage(request.getUrl(), driver.getPageSource());
driver.close(); // 看需要是否关闭浏览器
return page;
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
@Override
public void setThread(int i) {
}
//构建page返回对象
private Page createPage(String url, String content) {
Page page = new Page();
page.setRawText(content);
page.setUrl(new PlainText(url));
page.setRequest(new Request(url));
page.setDownloadSuccess(true);
return page;
}
}
2、自定义页面解析器
/**
* <h1>自定义页面解析器</h1>
* PageProcessor 负责解析页面,抽取有用信息,以及发现新的链接。
* WebMagic 使用 Jsoup 作为 HTML 解析工具,并基于其开发了解析 XPath 的工具 Xsoup。
* */
public class WNPageProcessor implements PageProcessor {
private Site site = Site.me()
.setCharset("UTF-8") // 设置编码
.setSleepTime(1) // 抓取间隔时间
.setTimeOut(1000 * 10) // 超时时间
.setRetrySleepTime(3000) // 重试时间
.setRetryTimes(3)
.addHeader("CSDN", "woniu")
.addHeader("Content-Type", "application/json;charset=UTF-8");
@Override
public void process(Page page) {
Html html = page.getHtml();
List<Selectable> hotSearchList = html.xpath("//*[@id=\"hotsearch-content-wrapper\"]/li").nodes();
System.out.println("今日百度热搜:");
// 遍历所有热搜新闻
for (Selectable hotSearch : hotSearchList){
List<Selectable> newsMetaList = hotSearch.xpath("//span/text()").nodes();
for (Selectable newsMeta : newsMetaList) {
System.out.print(newsMeta.get() + " ");
}
System.out.print("\n");
}
// 存储,可以传递到 WNPipeline
page.putField("woniu", "我是CSDN");
}
@Override
public Site getSite() {
return site;
}
}
3、自定义结果处理器
/**
* <h1>自定义结果处理器</h1>
* Pipeline负责抽取结果的处理,包括计算、持久化到文件、数据库等。
* WebMagic默认提供了“输出到控制台”和“保存到文件”两种结果处理方案。
* Pipeline定义了结果保存的方式,如果你要保存到指定数据库,则需要编写对应的Pipeline。
* 对于一类需求一般只需编写一个Pipeline。
* */
public class WNPipeline implements Pipeline {
@Override
public void process(ResultItems resultItems, Task task) {
// 获取封装好的数据
String woniu = resultItems.get("woniu");
System.out.println("WNPageProcessor 传递结果:" + woniu);
}
}
4、单元测试
public class WebMagicExample {
public static void main(String[] args) {
// 目标网页 URL
String url = "https://www.baidu.com";
Spider.create(new WNPageProcessor()) // 创建爬虫,并指定PageProcessor
.addUrl(url) // 添加需要爬取的URL
.setDownloader(new WNDownloader()) // 设置 Downloader,一个 Spider 只能有个一个 Downloader
.addPipeline(new WNPipeline()) // 添加一个 Pipeline,一个 Spider 可以有多个 Pipeline
.thread(5) // 开启5个线程抓取
.start(); // 开始爬取,设置最多在10分钟内停止
}
}
Selenium 可以配置为两种模式运行:有界面(headed)和无界面(headless)。
在默认情况下,Selenium WebDriver 会启动一个完整的浏览器窗口,用户可以直观地看到浏览器中的操作和页面变化,这对于测试和调试非常有用。如下图:
要启动无界面模式,需要在 Selenium 的浏览器配置中添加相应的参数。例如,在 Java 中使用ChromeDriver 时,可以通过以下代码启动无界面模式:
// 创建浏览器参数对象
ChromeOptions chromeOptions = new ChromeOptions();
// 设置为无界面浏览器模式,若是不想看到浏览器打开,就可以配置此项
chromeOptions.addArguments("--headless");
这段代码会启动一个没有图形界面的 Chrome 浏览器,并打开指定的网址。在无界面模式下,所有的 Selenium 操作都会正常执行,但不会有任何视觉反馈。
运行结果截图如下:
在谷歌 Chrome 浏览器中查找 HTML 元素的 XPath 路径,可以通过以下步骤进行:
使用快捷键 Ctrl + Shift + I 或 F12 打开 Chrome 的开发者工具,或者在页面上右键点击,选择“检查”来打开。
在开发者工具中,默认选中的是 “元素(Elements)” 面板,这里可以查看页面的 DOM 结构。
使用鼠标点击页面上的目标元素,或者使用开发者工具中的选择器工具(点击左上角的小箭头图标后,鼠标变为一个箭头状)来选择页面上的元素。
在元素(Elements)面板中,选中目标元素后,右键点击该元素的代码行,在弹出的菜单中选择“复制” > “复制 XPath”来复制 XPath 路径。如果想要复制完整的 XPath 路径(从根节点开始),可以选择“复制” > “复制完整 XPath”。
在开发者工具的控制台(Console)面板中,可以使用 XPath 表达式来验证路径是否正确。例如,输入$x(‘//XPath 表达式’)并回车,如果路径正确,控制台会输出匹配的元素数量
示例:$x(‘//*[@id=“hotsearch-content-wrapper”]’),如下图:
ChromeDriver 下载地址,请根据您使用的操作系统下载相应的 ChromeDriver 版本。
Jsoup 主要用于抓取和解析静态 HTML 页面,它不执行 JavaScript,因此对于依赖 JavaScript动态加载内容的网站可能无法获取完整的页面信息。而 HtmlUnit 和 WebMagic 则具备处理动态网页的能力。
HtmlUnit 是一个无头浏览器,它可以执行 JavaScript 代码,从而允许用户与动态内容进行交互,获取通过 JavaScript 动态加载的数据。这使得 HtmlUnit 非常适合抓取那些需要执行脚本才能显示完整内容的网站。
WebMagic 作为一个爬虫框架,它不仅支持静态页面的抓取,也能够通过内置的或自定义的处理器来处理动态内容。WebMagic 的多线程和分布式特性使其在大规模数据抓取方面表现出色,尤其适合于处理复杂的动态网站。
因此,在选择工具时,如果目标网站主要是静态内容,Jsoup 可能是一个简单且高效的选择。而如果网站包含大量的动态内容,HtmlUnit 和 WebMagic 将更能满足需求。
综上所述,Jsoup、HtmlUnit 和 WebMagic 各有千秋,它们分别适用于不同的网页抓取场景。通过合理选择和应用这些工具,开发者可以大幅提升工作效率,优化项目质量,从而在网络爬虫的开发之旅中取得成功。无论您的项目需求如何,这三款工具都能为您提供强大的支持,助您轻松应对网络数据抓取的挑战。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。