玩转Java网页抓取

— 使用Java进行网页抓取 —

用于网页抓取的流行语言有Python、JavaScript和Node.js、PHP、Java、C#等。因为有很多选择,想要确定哪种语言最合适并不容易。每种语言都有其优点和缺点。在本文中,我们将使用Java进行网页抓取并使用 Java创建一个网页抓取工具。

网页抓取框架

有两个最常用的Java网页抓取库——JSoupHtmlUnit

JSoup是一个强大的库,可以有效地处理格式错误的HTML。这个库的名字来自于短语“tag soup”,它指的是格式错误的HTML文档。

HtmlUnit是用于Java程序的无图形用户界面或无头的浏览器。它可以模拟浏览器的关键方面,例如从页面中获取特定元素、单击这些元素等。正如这个库的名称所暗示的那样,它通常用于单元测试。这是一种模拟浏览器以进行测试的方法。

HtmlUnit也可用于网页抓取。好消息是,只需一行,就可以关闭JavaScript和CSS。这个库对网页抓取很有帮助,因为大多数情况下不需要JavaScript和CSS。后面我们将检查这两个库并创建网页抓取工具。

使用Java构建网络爬虫的先决条件

本教程使用Java进行网页抓取,前提是您要熟悉Java编程语言。为了管理包,我们将使用Maven。

除了Java基础知识外,您需要对网站的工作原理有初步的了解。还需要对HTML和使用XPath或CSS Selectors选择其中的元素有很好的了解。请注意,并非所有库都支持XPath。

CSS Selectors的快速概览

在我们继续本Java网页抓取教程之前,先回顾一下CSS Selectors

#firstname–选择任何id等于“firstname”的元素

.blue–选择class包含“blue”的任何元素

p–选择所有<p>标签

div#firstname–选择等于“firstname”的div元素id

p.link.new–请注意,此处没有空格。选择<p class="link new">

p.link .new–请注意此处的空格。选择在<p class="link">里“new”类的任何元素

接下来,让我们回顾一下可用Java进行网页抓取的库。

Part 1 使用JSoup配合Java抓取网页

JSoup可能是使用Java进行网页抓取最常用的库了。让我们使用这个库来创建一个Java网页抓取工具。

总体来说,使用Java进行网页抓取涉及三个步骤

01.获取JSoup

使用Java进行网页抓取的第一步是获取Java库。Maven可以在这里提供帮助。使用任何Java IDE创建一个Maven项目。如果您不想使用Maven,请前往以下页面查找替代进行下载:

https://jsoup.org/download

pom.xml(Project Object Model)文件中,为依赖项添加一个新部分并为JSoup添加一个依赖项。该pom.xml文件如下:

<dependencies>
       <dependency>
          <groupId>org.jsoup</groupId>
          <artifactId>jsoup</artifactId>
       <version>1.14.1</version>
       </dependency>
</dependencies>

有了以上条件,我们就可以创建一个Java抓取工具了。

02.获取和解析HTML

使用Java进行网页抓取的第二步是从目标URL中获取HTML并将其解析为Java对象。让我们从导入开始:

import org.jsoup.Connection;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;

请注意,使用通配符导入所有内容-import org.jsoup.*.并不是一个好习惯。想要始终准确导入您需要的内容尽量少用通配符。上述导入是我们将在本Java网页抓取教程中使用的内容。

JSoup提供了这个connect功能。此函数连接URL并返回一个Document.以下是获取页面HTML的方法:

Document doc = Jsoup.connect("https://en.wikipedia.org/wiki/Jsoup").get();

您会经常在一些地方看到这行代码,但它有一个缺点。这种快捷的方式没有做任何错误处理。更好的方法是创建一个函数。此函数以URL作为参数。首先,创建一个连接并将其存储在一个变量中。之后,get()调用连接对象的方法来检索HTML文档。该文档作为Document类的实例返回。该get()方法可以抛出一个IOException,此IOException需要进行处理,如下:

public static Document getDocument(String url) {
    Connection conn = Jsoup.connect(url);
    Document document = null;
    try {
         document = conn.get();
    } catch (IOException e) {
         e.printStackTrace();
     // handle error
     }
     return document;
}

在某些情况下,您需要传递自定义用户代理。这可以通过userAgent()在调用函数之前将用户代理字符串发送到函数来完成get()

Connection conn = Jsoup.connect(url);
conn.userAgent("custom user agent");
document = conn.get();

此操作基本能解决遇到的常见问题。

03.查询HTML

任何Java网络爬虫构建过程中最关键的步骤是查询HTMLDocument对象以获取所需数据。这是您在用Java编写网络爬虫时花费大部分时间的地方。

JSoup支持多种提取所需元素的方法。比如getElementByIDgetElementsByTag等,使得它更容易查询DOM。

这是导航到Wikipedia上的JSoup页面示例。右键单击标题并选择“检查”,从而打开选定标题的开发人员工具。

具有唯一类的HTML元素

在这种情况下,可以使用getElementByIDgetElementsByClass。这里要注意的一个重点是getElementById(注意单数Element)返回一个Element对象,而getElementsByClass(注意复数Elements)返回Element对象的数组列表

这个Elements的非常方便,因为这个库有一个Elements的扩展ArrayList<Element>.这个扩展使代码更简洁并提供更多功能。

在下面的代码示例中,first()方法可用于从ArrayList.获取第一个元素,在获得元素的引用后,text()可以用来获取文本。

Element firstHeading = document.getElementsByClass("firstHeading").first(); 
System.out.println(firstHeading.text());

这些功能都不错;但是,它们仅限于JSoup。对于大多数情况,select函数可能是更好的选择。选择功能不起作用的唯一情况是您需要向上遍历文档的时候。在这些情况下,您可能需要使用parent(),children()和child()。有关所有可用方法的完整列表,请访问此页面:

https://jsoup.org/cookbook/extracting-data/dom-navigation

以下代码演示了如何使用selectFirst()方法,该方法会返回第一个匹配项。

Element firstHeading= document.selectFirst(".firstHeading");

在这个例子中,使用了selectFirst()方法。如果需要选择多个元素,可以使用该select()方法。将采用CSS Selector作为参数并返回一个实例Elements,它是类型ArrayList<Element>的扩展。

Part 2.使用HtmlUnit配合Java抓取网页

有很多方法可以读取和修改加载的页面。HtmlUnit可以像浏览器一样使网页交互变得容易,包括阅读文本、填写表单、单击按钮等。在这种情况下,我们将使用该库中的方法从URL读取信息。

如上一节所述,使用Java进行网页抓取涉及三个步骤。

01.获取和解析HTML

使用Java进行网页抓取的第一步是获取Java库。Maven可以在这里提供帮助。创建一个新的maven项目或使用在上一节中创建的项目。如果您不想使用Maven,请前往此页面查找替代进行下载:

https://sourceforge.net/projects/htmlunit/

在该pom.xml文件中,dependenciesHtmlUnit添加一个新部分并为其添加依赖项。该pom.xml文件将如下所示:

<dependency>
   <groupId>net.sourceforge.htmlunit</groupId>
   <artifactId>htmlunit</artifactId>
   <version>2.51.0</version>
</dependency>

02.获取HTML

使用Java进行网页抓取的第二步是从目标URL中检索HTML作为 Java对象。让我们从导入开始:

import com.gargoylesoftware.htmlunit.WebClient; 
import com.gargoylesoftware.htmlunit.html.DomNode; 
import com.gargoylesoftware.htmlunit.html.DomNodeList; 
import com.gargoylesoftware.htmlunit.html.HtmlElement; 
import com.gargoylesoftware.htmlunit.html.HtmlPage;

如上一节所述,执行通配符导入(例如import com.gargoylesoftware.htmlunit.html.*.)并不是一个好习惯。我们依旧不使用通配符,只导入我们需要的内容。这里导入的是我们将在本Java网页抓取教程中使用的内容。

在这个例子中,我们将抓取这个Librivox页面

HtmlUnit使用WebClient类来获取页面。第一步是创建此类的实例。在这个例子中,不需要CSS渲染,也没有使用JavaScript。我们可以设置选项来禁用这两个。

WebClient webClient = new WebClient(); 
webClient.getOptions().setCssEnabled(false); 
webClient.getOptions().setJavaScriptEnabled(false); 
HtmlPage page = webClient.getPage("https://librivox.org/the-first-men-in-the-moon-by-hg-wells");

请注意,getPage()函数可以抛出

IOException.您需要在try-catch中引用它。

以下是函数返回HtmlPage实例的一个实现示例:

public static HtmlPage getDocument(String url)  {
      HtmlPage page = null;
      try (final WebClient webClient = new WebClient()) {
           webClient.getOptions().setCssEnabled(false);
           webClient.getOptions().setJavaScriptEnabled(false);
           page = webClient.getPage(url);
      } catch (IOException e) {
           e.printStackTrace();
      }
      return page;
}

然后我们可以继续下一步。

03.查询HTML

有三类方法可以配合HTMLPage使用。第一个方法是利用DOM的方法,会使用getElementById()getElementByName()等,然后返回一个元素。这些也跟getElementsById()一样有类似的对应项,会返回所有匹配项。这类方法会返回一个DomElement对象或一个DomElement对象列表

HtmlPage page = webClient.getPage("https://en.wikipedia.org/wiki/Jsoup"); 
DomElement firstHeading = page.getElementById ("firstHeading"); 
System.out.print(firstHeading.asNormalizedText()); // prints Jsoup

第二类方法是使用XPath。在本Java网页抓取教程中,我们将使用Java创建一个网页抓取工具。

导航到此页面,右键单击书名,然后单击检查。如果您已经熟悉XPath,您应该能够看到选择书名的XPath是

//div[@class="content-wrap clearfix"]/h1.

通过Xpath选择元素

有两种方法可以使用XPath—getByXPath()和getFirstByXPath().它们返回HtmlElement而不是DomElement。请注意,引号等特殊字符需要使用反斜杠进行转义:

HtmlElement book = page.getFirstByXPath("//div[@class=\"content-wrap clearfix\"]/h1"); 
System.out.print(book.asNormalizedText());

最后,第三类方法是使用CSS选择器。这类方法是querySelector()querySelectorAll()。他们分别返回DomNodeDomNodeList<DomNode>

为了使这个Java网络爬虫教程更加真实,让我们打印页面中的所有章节名称、读者名称和阅读持续时间。第一步是确定可以选择所有行的选择器。接下来,我们将使用querySelectorAll()方法选择所有行。最后,我们将对所有行运行一个循环并调用querySelector()以提取每个单元格的内容。

String selector = ".chapter-download tbody tr";
DomNodeList<DomNode> rows = page.querySelectorAll(selector);
for (DomNode row : rows) {
    String chapter = row.querySelector("td:nth-child(2) a").asNormalizedText();
    String reader = row.querySelector("td:nth-child(3) a").asNormalizedText();
    String duration = row.querySelector("td:nth-child(4)").asNormalizedText();
    System.out.println(chapter + "\t " + reader + "\t " + duration);
}

—— 结论 ——

几乎每个企业都需要网络抓取来分析数据并在市场上保持竞争力。了解网页抓取的基础知识以及如何使用Java构建网页抓取工具可以最终帮助企业做出更明智、更快速的决策,这对于企业取得成功至关重要。在本文中,我们看到了两个Java网页抓取示例。

如果您已经了解Java,则可能不需要探索用于网络抓取的任何其他语言。不过,如果您想了解如何使用Python进行网页抓取,我们有一个关于Python 网页抓取的教程。还有一个关于使用JavaScript和 Node.js进行网页抓取的教程。所有这些文章都应该帮助您选择适合您特定需求的最佳编程语言。

常见问题

Q:您可以用Java抓取网页吗?

A:是的。有许多强大的Java库用于网页抓取。其中两个例子分别是JSoup和HtmlUnit。这些库可帮助您连接到网页并提供许多方法来提取所需的信息。如果您了解Java,那么使用这些Java库将花费很少的时间。

Q:网络抓取合法吗?

A:这是一个复杂的问题,需要详细检查。我们在“网络抓取合法吗?”中深入探讨了这个主题。我们强烈建议您阅读下这篇文章。简而言之,只要遵循有关源目标或数据本身的法律,网络抓取就是一项合法活动。

  • 3
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值