使用Jsoup来解析Html

使用Jsoup来解析Html

微信搜索 zze_coding 或扫描 👉 二维码关注我的微信公众号获取更多资源推送:

我们抓取到页面后,还需要对页面进行解析。可以使用字符串处理工具解析页面,也可以使用正则表达式,但是这些方法都会带来很大的开发成本,所以我们需要使用一款专门解析 HTML 页面的技术。

介绍

Jsoup 是一款 Java 的 HTML 解析起。可直接解析某个 URL 地址、HTML 文本内容。它提供了一套非常省力的 API,可通过 DOM、CSS 以及类似于 JQuery 的操作来取出和操作数据。
Jsoup 的主要功能如下:

  1. 从一个 URL、文件或字符串中解析 HTML。
  2. 使用 DOM 或 CSS 选择器来查找、取出数据。
  3. 可操作 HTML 元素、属性、文本。

使用

依赖

在 HttpClient 入门程序的基础上引入以下依赖。

<!--Jsoup 依赖-->
<dependency>
    <groupId>org.jsoup</groupId>
    <artifactId>jsoup</artifactId>
    <version>1.10.2</version>
</dependency>
<!--文件操作-->
<dependency>
    <groupId>commons-io</groupId>
    <artifactId>commons-io</artifactId>
    <version>2.4</version>
</dependency>
<!--字符串操作-->
<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-lang3</artifactId>
    <version>3.7</version>
</dependency>
<!--单元测试-->
<dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.12</version>
    <scope>test</scope>
</dependency>

解析URL

Jsoup 可以直接输入 URL,它会发起请求并获取数据,封装为 Document 对象。

// 解析 url 地址,第一个参数是访问的 url,第二个参数是用来设置访问的超时时间
Document doc = Jsoup.parse(new URL("http://www.zze.xyz"), 1000);
// 获取 title 标签的文本内容
String title = doc.getElementsByTag("title").first().text();
System.out.println(title); // 张种恩的个人博客

注:虽然使用 Jsoup 可以替代 HttpClient 直接发起请求解析数据,但是往往不会这样用,因为实际的开发过程中,需要使用到多线程、连接池、代理等等方式,而 Jsoup 对这些的支持并不是很好,所以我们一般把 Jsoup 仅仅作为 HTML 解析工具使用。

解析字符串

String htmlStr = null;
// 使用 HttpClient 获取到一个网页到 Html 字符串
CloseableHttpClient httpClient = HttpClients.createDefault();
HttpGet httpGet = new HttpGet("http://zze.xyz/article/100.html");
CloseableHttpResponse response = httpClient.execute(httpGet);
if (response.getStatusLine().getStatusCode() == 200) {
    HttpEntity httpEntity = response.getEntity();
    htmlStr = EntityUtils.toString(httpEntity);
}
// Jsoup 解析字符串
Document doc = Jsoup.parse(htmlStr, "UTF-8");
String title = doc.getElementsByTag("title").first().text();
System.out.println(title); // Mac使用笔记

解析文件

准备以下 HTML 文件:

<!-- testHtml.html -->
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>测试Jsoup解析文件</title>
</head>
<body>
张种恩的博客:www.zze.xyz
<p id="p_id">测试 document.getElementById()</p>
<p class="p_class">测试 document.getElementsByClass()</p>
<p class="p_class2">测试 document.getElementsByClass</p>
</body>
</html>

使用 Jsoup 解析该文件:

// 直接解析磁盘上的文件
Document doc = Jsoup.parse(new File("/Users/zhangzhongen/dev/idea/网络爬虫/crawler-first/src/main/resources/testHtml.html"), "UTF-8");
// 获取 body 标签内的文本内容
String bodyContent = doc.getElementsByTag("body").first().text();
// 输出
System.out.println(bodyContent); // 张种恩的博客:www.zze.xyz

使用Dom方式获取元素

Document doc = Jsoup.parse(new File("/Users/zhangzhongen/dev/idea/网络爬虫/crawler-first/src/main/resources/testHtml.html"), "UTF-8");
// 测试根据 id 获取元素
Element ele1 = doc.getElementById("p_id");
System.out.println(ele1);
//<p id="p_id">测试 document.getElementById()</p>

// 测试根据 class 获取元素
Element ele2 = doc.getElementsByClass("p_class").first();
System.out.println(ele2);
//<p class="p_class">测试 document.getElementsByClass()</p>

// 测试根据标签获取元素
Elements ele3 = doc.getElementsByTag("title");
System.out.println(ele3);
// <title>测试Jsoup解析文件</title>

// 测试根据属性获取元素
Elements ele4 = doc.getElementsByAttribute("class");
System.out.println(ele4);
//<p class="p_class">测试 document.getElementsByClass()</p>
//<p class="p_class2">测试 document.getElementsByClass</p>

// 测试根据属性和值获取元素
Elements ele5 = doc.getElementsByAttributeValue("class", "p_class2");
System.out.println(ele5);
//<p class="p_class2">测试 document.getElementsByClass</p>

从元素中获取数据

Document doc = Jsoup.parse(new File("/Users/zhangzhongen/dev/idea/网络爬虫/crawler-first/src/main/resources/testHtml.html"), "UTF-8");

// 获取元素的 id
Element ele1 = doc.getElementById("p_id");
System.out.println(ele1.id());
// p_id

// 获取元素的 class 名称
Elements ele2 = doc.getElementsByAttribute("class");
for (Element element : ele2) {
    System.out.println(element.classNames());
}
// [p_class]
// [p_class2]

// 从元素中获取属性的值
System.out.println(ele1.attr("id"));
// p_id

// 获取元素的所有属性
Attributes attributes = ele1.attributes();
for (Attribute attribute : attributes) {
    System.out.println(attribute);
}
// id="p_id"

// 从元素中获取文本内容
System.out.println(ele1.text());
// 测试 document.getElementById()

通过选择器获取元素

Jsoup 的选择器和 Css 选择器的使用方法相同,这里就不多赘述,直接看下面示例。

Document doc = Jsoup.parse(new File("/Users/zhangzhongen/dev/idea/网络爬虫/crawler-first/src/main/resources/testHtml.html"), "UTF-8");

// 根据标签获取元素
Elements ele1 = doc.select("title");
System.out.println(ele1);
//<title>测试Jsoup解析文件</title>

Elements ele2 = doc.select("#p_id");
System.out.println(ele2);
//<p id="p_id">测试 document.getElementById()</p>

// 通过 class 名称查找元素
Elements ele3 = doc.select(".p_class");
System.out.println(ele3);
//<p class="p_class">测试 document.getElementsByClass()</p>

// 通过属性名称查找元素
Elements ele4 = doc.select("[class]");
System.out.println(ele4);
//<p class="p_class">测试 document.getElementsByClass()</p>
//<p class="p_class2">测试 document.getElementsByClass</p>

// 通过属性名称和值获取元素
Elements ele5 = doc.select("[class=p_class]");
System.out.println(ele5);
//<p class="p_class">测试 document.getElementsByClass()</p>

使用组合选择器获取元素

Document doc = Jsoup.parse(new File("/Users/zhangzhongen/dev/idea/网络爬虫/crawler-first/src/main/resources/testHtml.html"), "UTF-8");
// 元素 + id
Elements ele1 = doc.select("p#p_id");
System.out.println(ele1);
//<p id="p_id">测试 document.getElementById()</p>

// 元素 + class
Elements ele2 = doc.select("p.p_class");
System.out.println(ele2);
//<p class="p_class">测试 document.getElementsByClass()</p>

// 元素 + 属性名
Elements ele3 = doc.select("meta[charset]");
System.out.println(ele3);
//<meta charset="UTF-8">

// 任意组合
Elements ele4 = doc.select("p[class].p_class2");
System.out.println(ele4);
//<p class="p_class2">测试 document.getElementsByClass</p>

// 查找某个元素下的子元素,如 查找 body 下所有的 p 标签
Elements ele5 = doc.select("body p");
System.out.println(ele5);
//<p class="p_class2">测试 document.getElementsByClass</p>
//<p id="p_id">测试 document.getElementById()</p>
//<p class="p_class">测试 document.getElementsByClass()</p>
//<p class="p_class2">测试 document.getElementsByClass</p>

// 查找某个父元素下的直接子元素 如查找 head 标签下的 title 标签
Elements ele6 = doc.select("head>title");
System.out.println(ele6);
//<title>测试Jsoup解析文件</title>

// 查找某个父元素下的所有直接子元素
Elements ele7 = doc.select("head>*");
System.out.println(ele7);
//<meta charset="UTF-8">
//<title>测试Jsoup解析文件</title>

Copyright: 采用 知识共享署名4.0 国际许可协议进行许可

Links: https://www.zze.xyz/archives/java-jsoup.html

Buy me a cup of coffee ☕.