ITmob-Ly
发布于 2024-03-08 / 155 阅读
0

在 Android/Kotlin/Java 中怎样使用 Jsoup 解析 HTML?

jsoup-banner

介绍:什么是 jsoup

工作中我们有时会遇到需要解析 HTML 文件的需求,比如获取某个网页的 title,favicon,某个标签的属性或内容,甚至是修改 HTML 页面等需求。如果自己编码来实现也可以,但 HTML 很复杂,自己解析会遇到各种情况需要处理。

本文介绍一个开源且功能强大的解析 HTML 的 Java 库:jsoup,简化了从 HTML 中解析数据的过程,可以解析 HTML 文件、HTML 格式的字符串,输入流、甚至提供了给定 URL 并解析返回的 HTML 页面的能力。并且 jsoup 使用的是相对宽松的 MIT 许可证。

jsoup 的主要功能:

  1. 从 URL、文件或字符串中抓取并解析 HTML
  2. 使用 DOM 遍历或 CSS 选择器查找并提取数据
  3. 操作 HTML 元素、属性和文本
  4. 清理不受信任的 HTML(以防止 XSS)
  5. 输出整洁的 HTML

如何使用 jsoup

这里以 Kotlin 中使用 jsoup 解析 HTML 为例进行介绍

1. 添加 Gradle 依赖项

dependencies {
     implementation("org.jsoup:jsoup:1.17.2")
}

2. 从字符串中解析 HTML

使用静态 Jsoup.parse(String html) 方法解析字符串中的 HTML

val html = ("<html><head><title>First parse</title></head>"
    + "<body><p>Parsed HTML into a doc.</p></body></html>")
val doc: Document = Jsoup.parse(html)

3. 从网络获取和解析 HTML 页面

如果页面来自网络,则可以使用 Jsoup.connect(String url) 方法获取和解析 HTML 页面

val doc: Document = Jsoup.connect("https://itmob.cn").get()

获取 HTML 页面的网络请求也可以设置各种参数:

val doc: Document = Jsoup.connect("https://itmob.cn")
    .userAgent("Mozilla")
    .timeout(5000)
    .data("name", "itmob.cn")
    .get()

4. 从文件加载和解析 HTML 文档

val input = File("/tmp/input.html")
val doc = Jsoup.parse(input, "UTF-8", "https://itmob.cn/")

5. 从元素中获取属性、文本和 HTML

val html = "<p>An <a href='https://itmob.cn/'><b>example</b></a> link.</p>"
val doc = Jsoup.parse(html)
val link: Element = doc.select("a").first()

// 使用 Element.text() 方法获取元素(及其组合子元素)上的文本
val text = doc.body().text() // "An example link"
// 使用 Node.attr(String key) 方法要获取属性的值
val linkHref: String = link.attr("href") // "https://itmob.cn/"
val linkText: String = link.text() // "example""

// 使用 Element.html() 或 Node.outerHtml() 获取 HTML 节点
val linkOuterH: String = link.outerHtml() // "<a href="https://itmob.cn"><b>example</b></a>"
val linkInnerH: String = link.html() // "<b>example</b>

6. 使用 DOM 方法导航文档

Element 类提供了一系列类似 DOM 操作的方法来查找元素、提取和操作其数据

val input = File("/tmp/input.html")
val doc = Jsoup.parse(input, "UTF-8", "https://itmob.cn/")

val content = doc.getElementById("content")
val links = content.getElementsByTag("a")
for (link in links) {
    val linkHref = link.attr("href")
    val linkText = link.text()
}

7. 使用 CSS 选择器查找元素

jsoup 支持 CSS 选择器语法来查找匹配元素,这允许非常强大和健壮的查询

val input = File("/tmp/input.html")
val doc = Jsoup.parse(input, "UTF-8", "https://itmob.cn/")

val links = doc.select("a[href]") // 有 href 属性的 a 标签
val pngs = doc.select("img[src$=.png]") // img with src ending .png

val masthead = doc.select("div.masthead").first() // div with class=masthead

val resultDivs = doc.select("h3.r > div") // direct div after h3
val resultAs = resultDivs.select("a") // A elements within resultDivs

8. 修改 HTML

  1. 设置属性值
// Elements 集合支持批量修改属性。例如,要向 div 内的每个 a 元素添加 rel="nofollow" 属性:
doc.select("div.comments a").attr("rel", "nofollow")
  1. 设置元素的 HTML 标签
val div = doc.select("div").first() // <div></div>

// 清除元素中所有现有的内部 HTML,并将其替换为已解析的 HTML。
div.html("<p>lorem ipsum</p>") // <div><p>lorem ipsum</p></div>

// 分别将 HTML 添加到元素内部 HTML 的开头或结尾
div.prepend("<p>First</p>")
div.append("<p>Last</p>") // now: <div><p>First</p><p>lorem ipsum</p><p>Last</p></div>

val span = doc.select("span").first() // <span>One</span>
// 将 HTML 包裹在元素的外部 HTML 周围。
span.wrap("<li><a href='https://itmob.cn/'></a></li>") // now: <li><a href="https://itmob.cn"><span>One</span></a></li>
  1. 设置元素的文本内容
val div = doc.select("div").first() // <div></div>

div.text("five > four") // <div>five &gt; four</div>

div.prepend("First ")
div.append(" Last") // now: <div>First five &gt; four Last</div>

关于 jsoup 的更多用法详见官方文档:Cookbook: recipes for using jsoup