Java JSoup
上次修改时间:2024 年 7 月 4 日
JSoup 教程是一个 JSoup HTML 解析器的入门指南。在本教程中,我们将从 HTML 字符串、本地 HTML 文件和网页中解析 HTML 数据。我们将对数据进行清理并执行 Google 搜索。
JSoup 是一个用于提取和操作 HTML 数据的 Java 库。 它实现了 HTML5 规范,并将 HTML 解析为与现代浏览器相同的 DOM。
使用 JSoup,我们可以
- 从 URL、文件或字符串中抓取和解析 HTML
- 使用 DOM 遍历或 CSS 选择器查找和提取数据
- 操作 HTML 元素、属性和文本
- 针对安全白名单清理用户提交的内容,以防止 XSS 攻击
- 输出整洁的 HTML
依赖
在本教程的示例中,我们使用以下 Maven 依赖项。
<dependency> <groupId>org.jsoup</groupId> <artifactId>jsoup</artifactId> <version>1.17.2</version> </dependency>
JSoup
类通过其静态方法提供对 jsoup 功能的核心公共访问点。 例如,clean
方法清理 HTML 代码,connect
方法创建到 URL 的连接,或者 parse
方法解析 HTML 内容。
HTML 文件
在某些示例中,我们使用以下 HTML 文件
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document title</title> </head> <body> <p>List of words</p> <ul> <li>dark</li> <li>smart</li> <li>war</li> <li>cloud</li> <li>park</li> <li>cup</li> <li>worm</li> <li>water</li> <li>rock</li> <li>warm</li> </ul> <footer>footer for words</footer> </body> </html>
解析 HTML 字符串
JSoup.parse
方法将 HTML 字符串解析为文档。
import org.jsoup.Jsoup; import org.jsoup.nodes.Document; void main() { String htmlString = """ <html><head><title>My title</title></head> <body>Body content</body></html>"""; Document doc = Jsoup.parse(htmlString); String title = doc.title(); String body = doc.body().text(); System.out.printf("Title: %s%n", title); System.out.printf("Body: %s", body); }
该示例解析 HTML 字符串并输出其标题和正文内容。
String htmlString = """ <html><head><title>My title</title></head> <body>Body content</body></html>""";
此字符串包含简单的 HTML 数据。
Document doc = Jsoup.parse(htmlString);
使用 Jsoup 的 parse
方法,我们解析 HTML 字符串。该方法返回一个 HTML 文档。
String title = doc.title();
文档的 title
方法获取文档标题元素的字符串内容。
String body = doc.body().text();
文档的 body
方法返回正文元素;它的 text
方法获取元素的文本。
JSoup 解析本地 HTML 文件
在第二个示例中,我们将解析一个本地 HTML 文件。 我们使用重载的 Jsoup.parse
方法,该方法将 File
对象作为其第一个参数。
<!DOCTYPE html> <html> <head> <title>My title</title> <meta charset="UTF-8"> </head> <body> <div id="mydiv">Contents of a div element</div> </body> </html>
对于本示例,我们使用上面的 HTML 文件。
import java.io.File; import java.io.IOException; import java.util.Optional; import org.jsoup.Jsoup; import org.jsoup.nodes.Document; import org.jsoup.nodes.Element; void main() throws IOException { String fileName = "src/main/resources/index.html"; Document doc = Jsoup.parse(new File(fileName), "utf-8"); Optional<Element> divTag = Optional.ofNullable(doc.getElementById("mydiv")); divTag.ifPresent(e -> System.out.println(e.text())); }
该示例解析 index.html
文件,该文件位于 src/main/resources/
目录中。
Document doc = Jsoup.parse(new File(fileName), "utf-8");
我们使用 Jsoup.parse
方法解析 HTML 文件。
Optional<Element> divTag = Optional.ofNullable(doc.getElementById("mydiv"));
使用文档的 getElementById
方法,我们通过其 ID 获取元素。
divTag.ifPresent(e -> System.out.println(e.text()));
标签的文本使用元素的 text
方法检索。
读取网站的标题
在以下示例中,我们抓取并解析一个网页并检索标题元素的内容。
import java.io.IOException; import org.jsoup.Jsoup; import org.jsoup.nodes.Document; void main() throws IOException { String url = "https://webcode.me"; Document doc = Jsoup.connect(url).get(); String title = doc.title(); System.out.println(title); }
在代码示例中,我们读取指定网页的标题。
Document doc = Jsoup.connect(url).get();
Jsoup 的 connect
方法创建到给定 URL 的连接。 get
方法执行 GET 请求并解析结果;它返回一个 HTML 文档。
String title = doc.title();
使用文档的 title
方法,我们获取 HTML 文档的标题。
读取网页
下一个示例检索网页的 HTML 源代码。
import java.io.IOException; import org.jsoup.Jsoup; void main() throws IOException { String webPage = "https://webcode.me"; String html = Jsoup.connect(webPage).get().html(); System.out.println(html); }
该示例打印网页的 HTML。
String html = Jsoup.connect(webPage).get().html();
html
方法返回元素的 HTML;在我们的例子中是整个文档的 HTML 源代码。
元数据信息
HTML 文档的元信息提供有关网页的结构化元数据,例如其描述和关键字。
import java.io.IOException; import java.util.Optional; import org.jsoup.Jsoup; import org.jsoup.nodes.Document; import org.jsoup.nodes.Element; void main() throws IOException { String url = "https://jsoup.org"; Document doc = Jsoup.connect(url).get(); Optional<Element> el1 = Optional.ofNullable(doc.select("meta[name=description]").first()); el1.ifPresent(e -> System.out.println(e.attr("content"))); Optional<Element> el2 = Optional.ofNullable(doc.select("meta[name=keywords]").first()); el2.ifPresent(e -> System.out.println(e.attr("content"))); }
该代码示例检索有关指定网页的元信息。
Optional<Element> el2 = Optional.ofNullable(doc.select("meta[name=keywords]").first()); el2.ifPresent(e -> System.out.println(e.attr("content")));
文档的 select
方法查找与给定查询匹配的元素。 first
方法返回第一个匹配的元素。 使用 attr
方法,我们获取 content
属性的值。 我们使用 Optional
来处理可能的 NullPointerException。
获取所有标签
要获取所有标签,我们将 *
字符传递给 select
方法。
import org.jsoup.Jsoup; import java.io.File; import java.io.IOException; void main() throws IOException { var fileName = "src/main/resources/words.html"; var myFile = new File(fileName); var doc = Jsoup.parse(myFile, "UTF-8"); var all = doc.body().select("*"); all.forEach(e -> System.out.println(e.tagName())); }
我们从 words.html
文档中获取所有标签。
var all = doc.body().select("*");
我们获取所有元素。
all.forEach(e -> System.out.println(e.tagName()));
我们遍历所有元素,并使用 tagName
打印它们的标签名称。
text 方法
text
方法获取此元素及其所有子元素的组合文本。 空格被规范化和修剪。
import org.jsoup.Jsoup; import org.jsoup.nodes.Element; import org.jsoup.select.Elements; import java.io.File; import java.io.IOException; import java.util.Optional; void main() throws IOException { var fileName = "src/main/resources/words.html"; var myFile = new File(fileName); var doc = Jsoup.parse(myFile, "UTF-8"); System.out.println(doc.text()); System.out.println("---------------------------"); System.out.println(doc.body().text()); System.out.println("---------------------------"); Optional<Element> e1 = Optional.ofNullable(doc.select("body>p").first()); e1.ifPresent(e -> System.out.println(e.text())); System.out.println("---------------------------"); Optional<Element> e2 = Optional.ofNullable(doc.select("body>ul").first()); e2.ifPresent(e -> System.out.println(e.text())); System.out.println("---------------------------"); e2.ifPresent(e -> { Elements lis = e.children(); Optional<Element> ch1 = Optional.ofNullable(lis.first()); ch1.ifPresent(ce -> System.out.println(ce.text())); Optional<Element> ch2 = Optional.ofNullable(lis.last()); ch2.ifPresent(ce -> System.out.println(ce.text())); }); }
在示例中,我们从整个文档、正文、段落、无序列表以及第一个和最后一个列表项中获取文本数据。
Document title List of words dark smart cloud park cup water rock footer for words --------------------------- List of words dark smart cloud park cup water rock footer for words --------------------------- List of words --------------------------- dark smart cloud park cup water rock --------------------------- dark rock
修改文本
重载的 text
方法设置指定元素的文本。
import org.jsoup.Jsoup; void main() { String htmlString = """ <html><head><title>My title</title></head> <body>Body content</body></html>"""; var doc = Jsoup.parse(htmlString); doc.body().text("Lorem ipsum dolor sit amet"); System.out.println(doc); }
在示例中,我们更改 body
标签内的文本。
修改文档
有多种方法可以修改 HTML 文档。 例如,append
方法附加一个标签,prepend
方法将一个标签前置到一个元素。
import org.jsoup.Jsoup; import org.jsoup.nodes.Element; import java.util.Optional; void main() { String htmlString = """ <html><head><title>My title</title></head> <body></body></html>"""; var doc = Jsoup.parse(htmlString); Optional<Element> bodyEl = Optional.ofNullable(doc.select("body").first()); bodyEl.ifPresent(e -> { e.append("<p>hello there!</p>"); e.prepend("<h1>Heading</h1>"); }); System.out.println(doc); }
在示例中,我们将 h1
和 p
标签添加到文档中。
<html> <head> <title>My title</title> </head> <body> <h1>Heading</h1> <p>hello there!</p> </body> </html>
解析链接
下一个示例从 HTML 页面解析链接。
import java.io.IOException; import org.jsoup.Jsoup; import org.jsoup.nodes.Document; import org.jsoup.nodes.Element; import org.jsoup.select.Elements; void main() throws IOException { String url = "https://jsoup.org"; Document document = Jsoup.connect(url).get(); Elements links = document.select("a[href]"); for (Element link : links) { System.out.println("link : " + link.attr("href")); System.out.println("text : " + link.text()); } }
在示例中,我们连接到一个网页并解析其所有链接元素。
Elements links = document.select("a[href]");
要获取链接列表,我们使用文档的 select
方法。
清理 HTML 数据
JSoup 提供了清理 HTML 数据的方法。
import org.jsoup.Jsoup; import org.jsoup.nodes.Document; import org.jsoup.safety.Cleaner; import org.jsoup.safety.Safelist; void main() { String htmlString = """ <html><head><title>My title</title></head> <body><center>Body content</center></body></html> """; boolean valid = Jsoup.isValid(htmlString, Safelist.basic()); if (valid) { System.out.println("The document is valid"); } else { System.out.println("The document is not valid."); System.out.println("Cleaned document"); Document dirtyDoc = Jsoup.parse(htmlString); Document cleanDoc = new Cleaner(Safelist.basic()).clean(dirtyDoc); System.out.println(cleanDoc.html()); } }
在示例中,我们清理并清除 HTML 数据。
String htmlString = """ <html><head><title>My title</title></head> <body><center>Body content</center></body></html> """;
HTML 字符串包含已弃用的 center 元素。
boolean valid = Jsoup.isValid(htmlString, Safelist.basic());
isValid
方法确定字符串是否为有效的 HTML。 白名单是可以传递到清理器的 HTML(元素和属性)的列表。 Whitelist.basic
定义了一组基本的干净 HTML 标签。
Document dirtyDoc = Jsoup.parse(htmlString); Document cleanDoc = new Cleaner(Safelist.basic()).clean(dirtyDoc);
在 Cleaner
的帮助下,我们清理了脏 HTML 文档。
The document is not valid. Cleaned document <html> <head></head> <body> Body content </body> </html>
我们可以看到 center 元素已被删除。
来源
本教程专门介绍 JSoup HTML 解析器。
作者
列出所有Java教程。