原文: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);

使用Jsoupparse()方法,我们解析 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 教程