原文:http://zetcode.com/java/jsoup/

JSoup 教程是 JSoup HTML 解析器的入门指南。 在本教程中,我们将解析 HTML 字符串,本地 HTML 文件和网页中的 HTML 数据。 我们将清理数据并执行 Google 搜索。

JSoup

JSoup 是用于提取和处理 HTML 数据的 Java 库。 它实现了 HTML5 规范,并将 HTML 解析为与现代浏览器相同的 DOM。 该项目的网站是 jsoup.org 。

JSoup 功能

使用 JSoup,我们能够:

  • 从 URL,文件或字符串中抓取并解析 HTML
  • 使用 DOM 遍历或 CSS 选择器查找和提取数据
  • 处理 HTML 元素,属性和文本
  • 根据安全的白名单清除用户提交的内容,以防止 XSS 攻击
  • 输出整洁的 HTML

JSoup Maven 依赖项

在本教程的示例中,我们使用以下 Maven 依赖关系。

  1. <dependency>
  2. <groupId>org.jsoup</groupId>
  3. <artifactId>jsoup</artifactId>
  4. <version>1.12.1</version>
  5. </dependency>

JSoup类

JSoup类通过其静态方法为 jsoup 函数提供了核心公共访问点。 例如,clean()方法清理 HTML 代码,connect()方法创建与 URL 的连接,或者parse()方法解析 HTML 内容。

JSoup 解析 HTML 字符串

在第一个示例中,我们将解析一个 HTML 字符串。

com/zetcode/JSoupFromStringEx.java

  1. package com.zetcode;
  2. import org.jsoup.Jsoup;
  3. import org.jsoup.nodes.Document;
  4. public class JSoupFromStringEx {
  5. public static void main(String[] args) {
  6. String htmlString = "<html><head><title>My title</title></head>"
  7. + "<body>Body content</body></html>";
  8. Document doc = Jsoup.parse(htmlString);
  9. String title = doc.title();
  10. String body = doc.body().text();
  11. System.out.printf("Title: %s%n", title);
  12. System.out.printf("Body: %s", body);
  13. }
  14. }

该示例分析 HTML 字符串并输出其标题和正文内容。

  1. String htmlString = "<html><head><title>My title</title></head>"
  2. + "<body>Body content</body></html>";

此字符串包含简单的 HTML 数据。

  1. Document doc = Jsoup.parse(htmlString);

使用Jsoup的parse()方法,我们解析 HTML 字符串。 该方法返回一个 HTML 文档。

  1. String title = doc.title();

文档的title()方法获取文档的title元素的字符串内容。

  1. String body = doc.body().text();

文档的body()方法返回body元素; 其text()方法获取元素的文本。

JSoup 解析本地 HTML 文件

在第二个示例中,我们将解析本地 HTML 文件。 我们使用重载的Jsoup.parse()方法,该方法将File对象作为其第一个参数。

index.html

  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <title>My title</title>
  5. <meta charset="UTF-8">
  6. </head>
  7. <body>
  8. <div id="mydiv">Contents of a div element</div>
  9. </body>
  10. </html>

对于示例,我们使用上面的 HTML 文件。

com/zetcode/JSoupFromFileEx.java

  1. package com.zetcode;
  2. import java.io.File;
  3. import java.io.IOException;
  4. import org.jsoup.Jsoup;
  5. import org.jsoup.nodes.Document;
  6. import org.jsoup.nodes.Element;
  7. public class JSoupFromFileEx {
  8. public static void main(String[] args) throws IOException {
  9. String fileName = "src/main/resources/index.html";
  10. Document doc = Jsoup.parse(new File(fileName), "utf-8");
  11. Element divTag = doc.getElementById("mydiv");
  12. System.out.println(divTag.text());
  13. }
  14. }

该示例将分析src/main/resources/目录中的index.html文件。

  1. Document doc = Jsoup.parse(new File(fileName), "utf-8");

我们使用Jsoup.parse()方法解析 HTML 文件。

  1. Element divTag = doc.getElementById("mydiv");

使用文档的getElementById()方法,我们通过元素的 ID 获得元素。

  1. System.out.println(divTag.text());

使用元素的text()方法检索标签的文本。

JSoup 读取网站的标题

在以下示例中,我们将抓取并解析网页,然后检索title元素的内容。

com/zetcode/JSoupTitleEx.java

  1. package com.zetcode;
  2. import java.io.IOException;
  3. import org.jsoup.Jsoup;
  4. import org.jsoup.nodes.Document;
  5. public class JSoupTitleEx {
  6. public static void main(String[] args) throws IOException {
  7. String url = "http://webcode.me";
  8. Document doc = Jsoup.connect(url).get();
  9. String title = doc.title();
  10. System.out.println(title);
  11. }
  12. }

在代码示例中,我们读取了指定网页的标题。

  1. Document doc = Jsoup.connect(url).get();

Jsoup 的connect()方法创建到给定 URL 的连接。 get()方法执行 GET 请求并解析结果; 它返回一个 HTML 文档。

  1. String title = doc.title();

使用文档的title()方法,我们获得 HTML 文档的标题。

JSoup 读取 HTML 源码

下一个示例检索网页的 HTML 源。

com/zetcode/JSoupHTMLSourceEx.java

  1. package com.zetcode;
  2. import java.io.IOException;
  3. import org.jsoup.Jsoup;
  4. public class JSoupHTMLSourceEx {
  5. public static void main(String[] args) throws IOException {
  6. String webPage = "http://webcode.me";
  7. String html = Jsoup.connect(webPage).get().html();
  8. System.out.println(html);
  9. }
  10. }

该示例打印网页的 HTML。

  1. String html = Jsoup.connect(webPage).get().html();

html()方法返回元素的 HTML; 在我们的案例中,整个文档的 HTML 源代码。

JSoup 获取信息

HTML 文档的元信息提供有关网页的结构化元数据,例如其描述和关键字。

com/zetcode/JSoupMetaInfoEx.java

  1. package com.zetcode;
  2. import java.io.IOException;
  3. import org.jsoup.Jsoup;
  4. import org.jsoup.nodes.Document;
  5. public class JSoupMetaInfoEx {
  6. public static void main(String[] args) throws IOException {
  7. String url = "http://www.jsoup.org";
  8. Document document = Jsoup.connect(url).get();
  9. String description = document.select("meta[name=description]").first().attr("content");
  10. System.out.println("Description : " + description);
  11. String keywords = document.select("meta[name=keywords]").first().attr("content");
  12. System.out.println("Keywords : " + keywords);
  13. }
  14. }

该代码示例检索有关指定网页的元信息。

  1. String keywords = document.select("meta[name=keywords]").first().attr("content");

文档的select()方法查找与给定查询匹配的元素。 first()方法返回第一个匹配的元素。 使用attr()方法,我们获得content属性的值。

JSoup 解析链接

下一个示例分析 HTML 页面中的链接。

com/zetcode/JSoupLinksEx.java

  1. package com.zetcode;
  2. import java.io.IOException;
  3. import org.jsoup.Jsoup;
  4. import org.jsoup.nodes.Document;
  5. import org.jsoup.nodes.Element;
  6. import org.jsoup.select.Elements;
  7. public class JSoupLinksEx {
  8. public static void main(String[] args) throws IOException {
  9. String url = "http://jsoup.org";
  10. Document document = Jsoup.connect(url).get();
  11. Elements links = document.select("a[href]");
  12. for (Element link : links) {
  13. System.out.println("link : " + link.attr("href"));
  14. System.out.println("text : " + link.text());
  15. }
  16. }
  17. }

在该示例中,我们连接到网页并解析其所有链接元素。

  1. Elements links = document.select("a[href]");

要获取链表,我们使用文档的select()方法。

JSoup 清理 HTML 数据

Jsoup 提供了用于清理 HTML 数据的方法。

com/zetcode/JSoupSanitizeEx.java

  1. package com.zetcode;
  2. import org.jsoup.Jsoup;
  3. import org.jsoup.nodes.Document;
  4. import org.jsoup.safety.Cleaner;
  5. import org.jsoup.safety.Whitelist;
  6. public class JSoupSanitizeEx {
  7. public static void main(String[] args) {
  8. String htmlString = "<html><head><title>My title</title></head>"
  9. + "<body><center>Body content</center></body></html>";
  10. boolean valid = Jsoup.isValid(htmlString, Whitelist.basic());
  11. if (valid) {
  12. System.out.println("The document is valid");
  13. } else {
  14. System.out.println("The document is not valid.");
  15. System.out.println("Cleaned document");
  16. Document dirtyDoc = Jsoup.parse(htmlString);
  17. Document cleanDoc = new Cleaner(Whitelist.basic()).clean(dirtyDoc);
  18. System.out.println(cleanDoc.html());
  19. }
  20. }
  21. }

在示例中,我们清理并清理 HTML 数据。

  1. String htmlString = "<html><head><title>My title</title></head>"
  2. + "<body><center>Body content</center></body></html>";

HTML 字符串包含不推荐使用的center元素。

  1. boolean valid = Jsoup.isValid(htmlString, Whitelist.basic());

isValid()方法确定字符串是否为有效的 HTML。 白名单是可以通过清除程序的 HTML(元素和属性)列表。 Whitelist.basic()定义了一组基本的干净 HTML 标记。

  1. Document dirtyDoc = Jsoup.parse(htmlString);
  2. Document cleanDoc = new Cleaner(Whitelist.basic()).clean(dirtyDoc);

借助Cleaner,我们清理了脏的 HTML 文档。

  1. The document is not valid.
  2. Cleaned document
  3. <html>
  4. <head></head>
  5. <body>
  6. Body content
  7. </body>
  8. </html>

这是程序的输出。 我们可以看到中心元素已被删除。

JSoup 执行 Google 搜索

以下示例使用 Jsoup 执行 Google 搜索。

com/zetcode/JsoupGoogleSearchEx.java

  1. package com.zetcode;
  2. import java.io.IOException;
  3. import java.util.HashSet;
  4. import java.util.Set;
  5. import java.util.regex.Matcher;
  6. import java.util.regex.Pattern;
  7. import org.jsoup.Jsoup;
  8. import org.jsoup.nodes.Document;
  9. import org.jsoup.nodes.Element;
  10. import org.jsoup.select.Elements;
  11. public class JsoupGoogleSearchEx {
  12. private static Matcher matcher;
  13. private static final String DOMAIN_NAME_PATTERN
  14. = "([a-zA-Z0-9](docs_java_[a-zA-Z0-9\\-]{0_61}[a-zA-Z0-9])?\\.)+[a-zA-Z]{2,15}";
  15. private static Pattern patrn = Pattern.compile(DOMAIN_NAME_PATTERN);
  16. public static String getDomainName(String url) {
  17. String domainName = "";
  18. matcher = patrn.matcher(url);
  19. if (matcher.find()) {
  20. domainName = matcher.group(0).toLowerCase().trim();
  21. }
  22. return domainName;
  23. }
  24. public static void main(String[] args) throws IOException {
  25. String query = "Milky Way";
  26. String url = "https://www.google.com/search?q=" + query + "&num=10";
  27. Document doc = Jsoup
  28. .connect(url)
  29. .userAgent("Jsoup client")
  30. .timeout(5000).get();
  31. Elements links = doc.select("a[href]");
  32. Set<String> result = new HashSet<>();
  33. for (Element link : links) {
  34. String attr1 = link.attr("href");
  35. String attr2 = link.attr("class");
  36. if (!attr2.startsWith("_Zkb") && attr1.startsWith("/url?q=")) {
  37. result.add(getDomainName(attr1));
  38. }
  39. }
  40. for (String el : result) {
  41. System.out.println(el);
  42. }
  43. }
  44. }

该示例为"Milky Way"一词创建搜索请求。 它会打印十个与该术语匹配的域名。

  1. private static final String DOMAIN_NAME_PATTERN
  2. = "([a-zA-Z0-9](docs_java_[a-zA-Z0-9\\-]{0_61}[a-zA-Z0-9])?\\.)+[a-zA-Z]{2,15}";
  3. private static Pattern patrn = Pattern.compile(DOMAIN_NAME_PATTERN);

Google 搜索返回长链接,我们要从中获取域名。 为此,我们使用正则表达式模式。

  1. public static String getDomainName(String url) {
  2. String domainName = "";
  3. matcher = patrn.matcher(url);
  4. if (matcher.find()) {
  5. domainName = matcher.group(0).toLowerCase().trim();
  6. }
  7. return domainName;
  8. }

getDomainName()使用正则表达式匹配器从搜索链接返回域名。

  1. String query = "Milky Way";

这是我们的搜索词。

  1. String url = "https://www.google.com/search?q=" + query + "&num=10";

这是执行 Google 搜索的网址。

  1. Document doc = Jsoup
  2. .connect(url)
  3. .userAgent("Jsoup client")
  4. .timeout(5000).get();

我们连接到 URL,设置 5s 超时,然后发送 GET 请求。 返回 HTML 文档。

  1. Elements links = doc.select("a[href]");

从文档中,我们选择链接。

  1. Set<String> result = new HashSet<>();
  2. for (Element link : links) {
  3. String attr1 = link.attr("href");
  4. String attr2 = link.attr("class");
  5. if (!attr2.startsWith("_Zkb") && attr1.startsWith("/url?q=")) {
  6. result.add(getDomainName(attr1));
  7. }
  8. }

我们寻找不具有class="_Zkb"属性并且具有href="/url?q="属性的链接。 请注意,这些是硬编码的值,将来可能会更改。

  1. for (String el : result) {
  2. System.out.println(el);
  3. }

最后,我们将域名打印到终端。

  1. en.wikipedia.org
  2. www.space.com
  3. www.nasa.gov
  4. sk.wikipedia.org
  5. www.bbc.co.uk
  6. imagine.gsfc.nasa.gov
  7. www.forbes.com
  8. www.milkywayproject.org
  9. www.youtube.com
  10. www.universetoday.com

这些是"Milky Way"一词的 Google 顶级搜索结果。

本教程专门针对 Jsoup HTML 解析器。

您可能也对相关教程感兴趣: Java 教程,用 Java 读取网页,用 Java 阅读文本文件或 Jtwig 教程。

列出所有 Java 教程。