in

Java网页抓取时防止IP封锁的初学者指南

Java网页抓取时防止IP封锁的初学者指南

使用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

java web scraping 1

点击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选项。

java web scraping 2

在包内,我们需要创建一个类。右键点击包,然后选择New class。勾选创建public static void main选项,这样可以省去一些输入:

java web scraping 3

就这样。你已经可以开始编写代码了!


使用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 web scraping 4

选择Java 11(或8)并保存。点击Apply and Close。这样,错误就消失了。

现在再次运行代码,你应该会看到这个友好的消息:

java web scraping 5

但截图保存在哪里了呢?

进入你的主文件夹 /eclipse-workspace/[project]/,你会看到你的截图。它应该命名为screenshot-chromium.png。另外,你也可以同样轻松地使用Chrome和Firefox进行抓取。只需将chromium()替换为它们各自的方法即可。

如果你多次执行这个操作,你的目标网站很可能会屏蔽你。让我们看看如何避免这种情况。


Java抓取不被屏蔽——使用Playwright认证代理

网页抓取是完全合法的。然而,公司通常不喜欢免费提供信息。因此,当你刚开始进行网页抓取时,网站屏蔽你是很常见的。为了避免被屏蔽,你需要了解网站是如何识别并屏蔽抓取工具的。

有几件事会立即暴露你。例如,没有任何用户元数据(浏览器、操作系统等信息)的请求很可能来自软件。除非你手动添加请求头,否则许多编码库不会为你自动添加这些信息。

但Playwright为你解决了这个问题。由于你的Java网页抓取请求使用了真实的浏览器,因此整个请求是100%合法的,只是由你的代码控制。

接下来,他们会查看其他方面,例如你的IP地址。如果你请求了很多页面,快速离开并在同一时间段内再次访问,这是你是机器人的迹象。但他们主要通过检查你的IP地址来识别。

因此,解决方案是使用代理服务器,这里我将以IPRoyal的住宅代理IP为例进行解说。通过它,你可以使用来自真实住宅用户的轮换IP地址。这可以隐藏你的真实地址,使网站所有者无法将这些请求关联起来。

注册该服务,你将获得客户端区域的访问权限。在那里你可以看到代理URL并设置你的凭证:

IPRoyal residential proxies dashboard

现在你只需要在你的Java网页抓取工具中使用这些信息,就可以开始了。

在第一步中,你保存了一个包含你IP地址的截图。它看起来是这样的:

java web scraping 7

你可以使用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中使用代理的截图:

java web scraping 8

这是一个完全不同的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();

这段代码应该保存一个搜索字段高亮显示的屏幕截图:

java web scraping 9

类似地,你可以与表单元素交互。例如,你可以在定位符之后使用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();

结果如下:

java web scraping 10

这还只是一部分, 另外在定位器、交互和模拟用户操作方面还有很多其他选项。使用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是一个非常棒的工具。在选择器、交互和数据处理方面还有很多其他选项,但希望这篇文章可以作为一个良好的起点。希望你喜欢这篇文章.

Written by 河小马

河小马是一位杰出的数字营销行业领袖,广告中国论坛的重要成员,其专业技能涵盖了PPC广告、域名停放、网站开发、联盟营销以及跨境电商咨询等多个领域。作为一位资深程序开发者,他不仅具备强大的技术能力,而且在出海网络营销方面拥有超过13年的经验。