使用Java进行网页抓取变得更加简单了。网页抓取是现代企业的绝佳工具。通过它,你可以大规模收集数据、自动化操作、监控市场变化等等。信息就是力量,而网页抓取是获取无限信息的可靠来源。不过,这并不容易。”
每个目标网站都需要特定的代码。你还可能会被封锁。提取HTML数据也可能很困难。最重要的是,大多数关于Java网页抓取的指南都已经过时了。旧的解析器、不支持的库、正则表达式,这些都可以抛弃了。
今天,你将学习一种简单的方法来使用Java抓取任何网站,无论它多么复杂。此外,你还将学习如何避免被封锁,以及如何使用网页抓取工具截取屏幕和提取数据。让我们开始吧!
Java网页抓取是如何工作的?
一般来说,有很多方法可以抓取网页。在过去,常见的方法是从目标网站获取HTML代码,然后使用正则表达式提取数据。
这种方法适用于基本的网站,但设置起来相当复杂。而且,你需要找到完美的规则来提取你想要的元素。
后来,出现了一些代码解析器库,它们可以模拟浏览器。这是一个进步,但仍然非常有限。考虑到现在大多数网站都严重依赖动态元素,这种方法已经不够用了。
大多数教程到这里就结束了。而我们在这里告诉你——有更好的方法。
最好的Java网页抓取库—Playwright
进行网页抓取的最佳方法是使用无头浏览器。无头浏览器允许你使用编程语言来控制浏览器动作。有很多不错的选择,其中最受欢迎的是Puppeteer。
然而,Java没有Puppeteer库。但是有一个更好的选择——Playwright。
Playwright是Puppeteer的进化版。它具有相同的功能和更多的功能,而且使用起来同样简单。通过它,你可以创建一个浏览器窗口,将其存储在变量中,导航到一个页面,执行操作,还可以提取数据。
它允许你使用xPath、vue/react选择器、布局属性(在特定元素的左侧)或CSS代码来定位元素。你还可以通过文本内容,甚至结合CSS和文本选择器来定位它们。例如,如果你正在构建一个价格监控器,你可以定位包含“价格”字样的元素,以及主容器内的元素。
此外,无头浏览器可以很好地处理常规数据收集,例如连接API或获取XHR调用的数据。
现在让我们看看你可以做些什么。
Playwright、Java和一些示例
今天,我们将从零开始进行数据抓取。换句话说,我们将涵盖从安装IDE的基础知识到处理数据的所有内容。
我们的主要目标如下:
- 安装Java IDE
- 安装Playwright
- 解决常见问题
- 连接到网站
- 截取屏幕截图
- 使用认证代理连接到网站
- 收集数据
以下是你可以这样做的方法。
使用Java进行网页抓取——初学者指南
使用Java进行网页抓取的一个好处是它可以在任何地方运行。一旦编译了代码,你可以在任何操作系统上运行它。这在你有多台电脑并需要在它们之间切换时非常方便。
因此,你需要一个代码编辑器和编译器。如果你还没有安装IDE,我们推荐使用Eclipse,因为它非常容易上手。
接下来你需要安装Maven。如果你使用的是Eclipse,不需要单独安装Maven,但根据你使用的IDE不同,可能需要安装它。使用Maven,你可以轻松地构建包含外部依赖项的项目,而无需手动下载它们。
在Eclipse中,依次点击File > New > Other(快捷键Command N),搜索Maven并选择Maven Project。
点击Next。选择你的项目位置,并勾选‘Simple project’选项以跳过原型选择。然后填写你的Group ID、Artifact ID和项目的其他详细信息。最后,点击Finish。
你应该会在Package Explorer中看到一个新项目。等待几秒钟,你会看到文件和依赖项被创建。
接下来,打开pom.xml文件。这个文件告诉Maven这个项目是什么类型、有哪些依赖项等等。以下是原始文件内容:
<code class="language-java"><project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.iproyal</groupId> <artifactId>com.iproyal.webscraper</artifactId> <version>0.0.1-SNAPSHOT</version> </project>
在关闭标签之前,你需要添加一些数据来加载Playwright。你可以这样做:
<code class="language-java"><project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.iproyal</groupId> <artifactId>com.iproyal.webscraper</artifactId> <version>0.0.1-SNAPSHOT</version> <dependencies> <dependency> <groupId>com.microsoft.playwright</groupId> <artifactId>playwright</artifactId> <version>1.27.0</version> </dependency> </dependencies> </project>
设置基本完成了。现在我们来创建你的包和主类。
右键点击src/main/java文件夹,选择New package。确保不要勾选Create package-info.java选项。
在包内,我们需要创建一个类。右键点击包,然后选择New class。勾选创建public static void main选项,这样可以省去一些输入:
就这样。你已经可以开始编写代码了!
使用Java进行屏幕抓取
现在你只需要在这里添加你的抓取代码,编译它,然后你会在控制台看到结果。如果有任何错误,你的IDE会高亮显示出来。
让我们从一个简单的例子开始,截取屏幕截图。为了方便起见,在文件开头使用以下代码来进行所有示例。有时你可能会看到一些包未使用的警告,但你可以忽略它们。
package com.iproyal.com.iproyal.scraper; // import playwright and the proxy packages import com.microsoft.playwright.*; import com.microsoft.playwright.options.Proxy; // import some useful packages import java.nio.file.Paths; import java.util.Arrays; import java.util.List;
接下来,使用以下代码作为你的public static void main类:
public static void main(String[] args) { try (Playwright playwright = Playwright.create()) { BrowserType.LaunchOptions launchOptions = new BrowserType.LaunchOptions(); try (Browser browser = playwright.chromium().launch(launchOptions)) { BrowserContext context = browser.newContext(); Page page = context.newPage(); page.navigate("https://ipv4.icanhazip.com/"); page.screenshot(new Page.ScreenshotOptions().setPath(Paths.get("screenshot-" playwright.chromium().name() ".png"))); System.out.println("Screenshot taken"); context.close(); browser.close(); } } } }
这段代码尝试使用Playwright.create()来打开Playwright。然后它保存了LaunchOptions,但这部分稍后再说。接下来,代码片段使用playwright.chromium().launch(launchOptions)打开一个Chromium浏览器实例。
接下来,它的用法与Puppeteer非常相似。使用newPage()打开一个新页面,并使用page.navigate(“https://ipv4.icanhazip.com/”)进行导航。你可以使用page.screenshot(new Page.ScreenshotOptions().setPath(Paths.get(“screenshot-“ playwright.chromium().name() “.png”)))来截取屏幕截图。
这些方法中的每一个都有自定义选项。例如,如果你想指定浏览器窗口的大小,你可以这样做。你还可以为你的截图添加一个特定的文件名,就像我们在这里做的那样。
运行这段代码,如果你没有更改Eclipse中的其他设置,你应该会看到一个错误。大概是这样的:
Exception in thread "main" java.lang.Error: Unresolved compilation problem:
References to interface static methods are allowed only at source level 1.8 or above
但这很容易解决。右键单击项目,选择Properties。然后转到Libraries选项卡并单击JRE版本> Edit。
选择Java 11(或8)并保存。点击Apply and Close。这样,错误就消失了。
现在再次运行代码,你应该会看到这个友好的消息:
但截图保存在哪里了呢?
进入你的主文件夹 /eclipse-workspace/[project]/,你会看到你的截图。它应该命名为screenshot-chromium.png。另外,你也可以同样轻松地使用Chrome和Firefox进行抓取。只需将chromium()替换为它们各自的方法即可。
如果你多次执行这个操作,你的目标网站很可能会屏蔽你。让我们看看如何避免这种情况。
Java抓取不被屏蔽——使用Playwright认证代理
网页抓取是完全合法的。然而,公司通常不喜欢免费提供信息。因此,当你刚开始进行网页抓取时,网站屏蔽你是很常见的。为了避免被屏蔽,你需要了解网站是如何识别并屏蔽抓取工具的。
有几件事会立即暴露你。例如,没有任何用户元数据(浏览器、操作系统等信息)的请求很可能来自软件。除非你手动添加请求头,否则许多编码库不会为你自动添加这些信息。
但Playwright为你解决了这个问题。由于你的Java网页抓取请求使用了真实的浏览器,因此整个请求是100%合法的,只是由你的代码控制。
接下来,他们会查看其他方面,例如你的IP地址。如果你请求了很多页面,快速离开并在同一时间段内再次访问,这是你是机器人的迹象。但他们主要通过检查你的IP地址来识别。
因此,解决方案是使用代理服务器,这里我将以IPRoyal的住宅代理IP为例进行解说。通过它,你可以使用来自真实住宅用户的轮换IP地址。这可以隐藏你的真实地址,使网站所有者无法将这些请求关联起来。
注册该服务,你将获得客户端区域的访问权限。在那里你可以看到代理URL并设置你的凭证:
现在你只需要在你的Java网页抓取工具中使用这些信息,就可以开始了。
在第一步中,你保存了一个包含你IP地址的截图。它看起来是这样的:
你可以使用LaunchOptions连接到IPRoyal,并在请求中使用代理。以下是实现这一功能的主类代码:
public static void main(String[] args) { try (Playwright playwright = Playwright.create()) { BrowserType.LaunchOptions launchOptions = new BrowserType.LaunchOptions(); launchOptions.setProxy( new Proxy("http://geo.iproyal.com:12321") .setUsername("username") .setPassword("password") ); try (Browser browser = playwright.chromium().launch(launchOptions)) { BrowserContext context = browser.newContext(); Page page = context.newPage(); page.navigate("https://ipv4.icanhazip.com/"); page.screenshot(new Page.ScreenshotOptions().setPath(Paths.get("screenshot-" playwright.chromium().name() ".png"))); System.out.println("Screenshot taken"); context.close(); browser.close(); } } }
整个主类保持不变,但是现在使用setProxy方法来使用代理,然后添加用户名和密码。这是在你的Java web scraper中使用代理的截图:
这是一个完全不同的IP地址。所以,据网站所有者所知,这是两个不同的用户访问他们的网站。如果启用IP轮换,则该地址也会因每个请求而更改,因此很难检测到。
使用Java抓取数据
除了截图之外,你还可以截取自定义截图(全页面、特定元素),从页面元素中获取数据,并与页面进行交互。让我们看看一些例子。
为了方便起见,以下所有示例都放在这个代码块中:
try (Browser browser = playwright.chromium().launch(launchOptions)) { }
如果要选择一个元素,可以使用.locator方法。然后你可以提取它的文本内容,如果你想。例如:
BrowserContext context = browser.newContext(); Page page = context.newPage(); page.navigate("https://playwright.dev/java/"); String title = page.locator(".hero__title").innerText(); System.out.println("Hero title: " title); context.close(); browser.close();
这段代码加载了Playwright网站。然后它查找.hero__title CSS类并提取其文本。你可以对这个变量做任何你想做的事情。在我们的例子中,它只是一个简单的打印。然而,你也可以对其进行操作、将其保存到数据库、与其他值进行比较等。
你可以在定位器之后使用.click()方法点击元素,像这样:
BrowserContext context = browser.newContext(); Page page = context.newPage(); page.navigate("https://playwright.dev/java/"); page.locator(".DocSearch-Button").click(); page.screenshot(new Page.ScreenshotOptions().setPath(Paths.get("screenshot-1.png"))); System.out.println("Screenshot taken"); context.close(); browser.close();
这段代码应该保存一个搜索字段高亮显示的屏幕截图:
类似地,你可以与表单元素交互。例如,你可以在定位符之后使用fill()方法填充文本框。
BrowserContext context = browser.newContext(); Page page = context.newPage(); page.navigate("https://playwright.dev/java/"); page.locator(".DocSearch-Button").click(); page.locator("#docsearch-input").fill("test"); page.screenshot(new Page.ScreenshotOptions().setPath(Paths.get("screenshot-1.png"))); System.out.println("Screenshot taken"); context.close(); browser.close();
结果如下:
这还只是一部分, 另外在定位器、交互和模拟用户操作方面还有很多其他选项。使用Playwright Java,你几乎可以做任何一个真实用户会做的事情。
常见问题
必须声明一个命名包eclipse,因为这个编译单元与命名模块相关联。
从你的项目中删除module-info.java文件,这个错误就会消失。
接口静态方法的引用仅在源级别1.8或以上才允许。
正如我们在文章中探讨的那样,你可以在项目(右键点击)> 属性 > 库 > 选择你的项目的JRE > 编辑 > 选择不同的Java版本(11是不错的选择)> 完成 > 应用并关闭下修复这个问题。
如果你没有看到Java 11作为选项,你可以下载它到你的操作系统中。你可以在这里找到它。
Playwright Proxy不能解析为type > import
如果你在项目中看到这个错误,确保在文件开头添加以下内容:
import com.microsoft.playwright.options.Proxy;
有时即使有playwright.*行,代理选项也不会加载。
总 结
今天你学会了如何进行Java网页抓取而不被屏蔽。我们还探索了许多可以轻松获取和处理业务数据的现代技术。
Playwright是一个非常棒的工具。在选择器、交互和数据处理方面还有很多其他选项,但希望这篇文章可以作为一个良好的起点。希望你喜欢这篇文章.