jsoup
jsoup 是一个用于解析、提取和处理 HTML 的 Java 库。它提供了一个非常方便的 API,可以让开发者轻松地从 URL、文件或字符串中解析 HTML,并提取所需的内容。本文将带你深入了解 jsoup 的基础知识、核心对象以及常用的选择器语法,并通过实际案例演示其应用。
jsoup 基础
1.1 jsoup 入门案例
1.1.1 创建工程 se-jsoup-demo1
首先,创建一个新的 Maven 工程,命名为se-jsoup-demo1
。在项目的pom.xml
文件中添加 jsoup 的依赖:
<dependency>
<groupId>org.jsoup</groupId>
<artifactId>jsoup</artifactId>
<version>1.12.1</version>
</dependency>
1.1.2 获取网页源码
在爬取网页时,通常会使用HttpClient
等框架获取网页源码。获取到源码后,需要从中提取所需的内容,这时就可以使用 jsoup 这样的 HTML 解析器来实现。jsoup 支持解析 HTML 字符串、URL 和文件,并将其转换为org.jsoup.nodes.Document
对象,方便进一步操作。
以下是一个简单的示例,展示如何获取网页的标题:
import java.io.IOException;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
public class JsoupExampleGetTitle {
public static void main(String[] args) {
Document doc = null;
try {
doc = Jsoup.connect("http://www.baidu.com/").get();
} catch (IOException e) {
e.printStackTrace();
}
String title = doc.title();
System.out.println(title);
}
}
输出结果:
百度一下,你就知道
接下来是一个获取网页源码的示例:
package com.uairobot.bill.study.jsoup;
import java.io.IOException;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
public class JsonSourceContent {
public static void main(String[] args) {
Document document = null;
try {
document = Jsoup.connect("http://www.baidu.com").get();
} catch (IOException e) {
e.printStackTrace();
}
String text = document.text();
String outerHtml = document.outerHtml();
System.out.println("text");
System.out.println(text);
System.out.println("outerHtml");
System.out.println(outerHtml);
}
}
获取网页内容的方法:
Element.text()
: 获取元素中的纯文本。Element.html()
或Node.outerHtml()
: 获取元素中的 HTML 内容。Node.attr(String key)
: 获取元素的属性值,例如获取<a href="">
中的href
值。
1.1.3 登录获取 cookie
有时需要模拟登录操作并获取返回的 cookie。以下示例展示了如何通过 jsoup 连接并获取登录后的 cookie:
package com.uairobot.bill.study.jsoup;
import java.io.IOException;
import java.util.Map;
import org.jsoup.Connection;
import org.jsoup.Connection.Response;
import org.jsoup.Jsoup;
public class JsonLogin {
public static void main(String[] args) {
String url = "http://www.iotcloud168.com:8083/user/login?username=181228001&password=123";
Connection connect = Jsoup.connect(url);
Response execute = null;
try {
execute = connect.execute();
} catch (IOException e) {
e.printStackTrace();
}
Map<String, String> cookies = execute.cookies();
System.out.println(cookies);
}
}
1.2 jsoup Document 对象
1.2.1 获取 Document 对象
获取Document
对象的方法主要有以下几种:
从 URL 获取 HTML 解析:
Document doc = Jsoup.connect("http://www.baidu.com/").get();
Jsoup.connect("xxx")
方法返回一个org.jsoup.Connection
对象。在执行请求前,可以通过该对象设置请求信息,如头信息、cookie、超时时间、代理等,以模拟浏览器行为。例如:Document doc = Jsoup.connect("http://example.com") .data("query", "Java") .userAgent("Mozilla") .cookie("auth", "token") .timeout(3000) .post();
从文件获取 HTML 解析:
String addr = "http://zszcba.haedu.gov.cn/result/query"; File input = new File("example.html"); try { Document parse = Jsoup.parse(input, "UTF-8", addr); } catch (IOException e) { e.printStackTrace(); }
1.2.2 从 Document 获取指定的元素
Document
对象提供了多种方法来获取指定的 HTML 元素:
通过 DOM 方式获取:
getElementById(String id)
: 通过 ID 获取元素。getElementsByTag(String tagName)
: 通过标签名获取元素。getElementsByClass(String className)
: 通过类名获取元素。getElementsByAttribute(String key)
: 通过属性名获取元素。getElementsByAttributeValue(String key, String value)
: 通过指定的属性名和值获取元素。getAllElements()
: 获取所有元素。
通过选择器语法获取:
使用类似 CSS 或 jQuery 的选择器,通过
Element
类的select
方法来查找元素。例如:File input = new File("/tmp/input.html"); Document doc = Jsoup.parse(input, "UTF-8", "http://example.com/"); Elements links = doc.select("a[href]"); // 选择所有带有href属性的a标签 Elements pngs = doc.select("img[src$=.png]"); // 选择所有扩展名为.png的图片 Element masthead = doc.select("div.masthead").first(); // 选择class为masthead的div标签 Elements resultLinks = doc.select("h3.r > a"); // 选择h3标签内的a标签
1.3 选择器的语法
选择器是 jsoup 中非常强大的功能,允许开发者通过类似 CSS 的语法来查找和过滤元素。
1.3.1 通过标签查找元素
选择器语法支持多种方式通过标签查找元素:
- 标签名:
a
- 选择所有<a>
标签。 - 命名空间标签:
ns|tag
- 例如,fb|name
选择<fb:name>
元素。 - ID 选择器:
#id
- 例如,#logo
选择 ID 为logo
的元素。 - 类选择器:
.class
- 例如,.masthead
选择所有类名包含masthead
的元素。 - 属性选择器:
[attribute]
- 选择拥有指定属性的元素,例如[href]
。[attr=value]
- 选择属性值等于指定值的元素,例如[width=500]
。[attr^=value]
,[attr$=value]
,[attr*=value]
- 分别选择属性值以指定值开头、结尾或包含指定值的元素。[attr~=regex]
- 选择属性值匹配指定正则表达式的元素,例如img[src~=(?i).(png|jpe?g)]
。
- 通配符:
*
- 匹配所有元素。
组合使用选择器:
el#id
: 元素加 ID,例如div#logo
。el.class
: 元素加类,例如div.masthead
。el[attr]
: 元素加属性,例如a[href]
。- 多种选择器组合,例如
a[href].highlight
。 - 层级关系选择器:
ancestor child
: 选择某元素下的子元素,例如.body p
选择.body
元素下的所有<p>
元素。parent > child
: 选择父元素的直接子元素,例如div.content > p
。siblingA + siblingB
: 选择紧接在siblingA
之后的同级元素siblingB
,例如div.head + div
。siblingA ~ siblingX
: 选择siblingA
之前的所有同级元素siblingX
,例如h1 ~ p
。
- 多个选择器:
el, el, el
- 选择匹配任一选择器的元素,例如div.masthead, div.logo
。
1.3.2 伪选择器
jsoup 支持多种伪选择器,用于进一步过滤元素:
:lt(n)
: 选择同级索引值小于 n 的元素,例如td:lt(3)
选择前三个<td>
元素。:gt(n)
: 选择同级索引值大于 n 的元素,例如div p:gt(2)
选择包含超过两个<p>
元素的<div>
。:eq(n)
: 选择同级索引值等于 n 的元素,例如form input:eq(1)
选择表单中的第二个<input>
元素。:has(selector)
: 选择包含匹配选择器的子元素的元素,例如div:has(p)
选择包含<p>
元素的所有<div>
。:not(selector)
: 选择不匹配选择器的元素,例如div:not(.logo)
选择所有不包含class="logo"
的<div>
元素。:contains(text)
: 选择包含指定文本的元素,搜索不区分大小写,例如p:contains(jsoup)
。:containsOwn(text)
: 选择直接包含指定文本的元素。:matches(regex)
: 选择文本匹配指定正则表达式的元素,例如div:matches((?i)login)
。:matchesOwn(regex)
: 选择自身文本匹配指定正则表达式的元素。
注意: 伪选择器中的索引从 0 开始,第一个元素索引为 0,第二个为 1,以此类推。
1.3.3 获取 Element 对象内容
从Element
对象中提取内容常用的方法包括:
- 获取文本:
Element.text()
String text = element.text();
- 获取 HTML 内容:
Element.html()
或Node.outerHtml()
String htmlContent = element.html(); String outerHtml = element.outerHtml();
- 获取属性值:
Node.attr(String key)
String href = element.attr("href");
1.4 jsoup 获取元素属性案例
1.4.1 获取 A 标签的链接
以下示例展示了如何使用 jsoup 获取特定条件下的<a>
标签链接:
package com.litong.jsoup.demo;
import java.io.IOException;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import lombok.extern.slf4j.Slf4j;
/**
* @author
* @date 2020年11月12日
* @version 1.0
* @desc 获取所有2020年高职扩招的学校
*/
@Slf4j
public class GetAllSchoolName {
public static void main(String[] args) throws IOException {
String httpUrl = "http://xxx/result/query";
for (int i = 1; i < 6; i++) {
// 连接并获取HTML文档
Document document = Jsoup.connect(httpUrl + "?page=" + i).get();
log.info("爬取第" + i + "页");
// 使用选择器获取包含特定文本的a标签
Elements select1 = document.select("td a[href]:contains(2020年高职扩招)");
Elements select2 = document.select("td a[href]:contains(2020年扩招)");
// 合并两个Elements对象
select1.addAll(select2);
log.info("共有学校" + select1.size() + "个");
// 获取学校的名称和链接
if (select1.size() > 0) {
for (Element element : select1) {
String text = element.text();
String value = element.attr("href");
log.info("获取到学校的名称: {}, 学校的连接: {}", text, value);
}
}
}
}
}
说明:
- 连接与获取文档: 使用
Jsoup.connect(url).get()
连接指定 URL 并获取 HTML 文档。 - 选择器使用: 使用
select
方法结合contains
伪选择器,筛选出包含特定文本的<a>
标签。 - 合并元素: 将两个
Elements
对象合并,避免遗漏任何符合条件的元素。 - 提取内容: 遍历
Elements
,提取每个<a>
标签的文本和href
属性值。
案例演示
通过上述内容,我们已经了解了 jsoup 的基础用法。接下来,我们将结合实际场景,展示如何使用 jsoup 进行网页数据的抓取与解析。
示例场景: 抓取高校扩招信息
假设我们需要抓取某教育网站上 2020 年高职扩招的所有学校名称及其链接。以下是详细步骤:
- 确定目标 URL:
http://xxx/result/query?page=1
到http://xxx/result/query?page=5
- 分析网页结构: 通过浏览器的开发者工具,确定目标数据所在的 HTML 标签及其属性。
- 编写爬虫代码: 使用 jsoup 连接每一页,提取目标数据。
完整代码示例:
package com.litong.jsoup.demo;
import java.io.IOException;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import lombok.extern.slf4j.Slf4j;
/**
* 获取所有2020年高职扩招的学校
*/
@Slf4j
public class GetAllSchoolName {
public static void main(String[] args) throws IOException {
String httpUrl = "http://xxx/result/query";
for (int i = 1; i < 6; i++) {
// 连接并获取HTML文档
Document document = Jsoup.connect(httpUrl + "?page=" + i).get();
log.info("爬取第" + i + "页");
// 使用选择器获取包含特定文本的a标签
Elements select1 = document.select("td a[href]:contains(2020年高职扩招)");
Elements select2 = document.select("td a[href]:contains(2020年扩招)");
// 合并两个Elements对象
select1.addAll(select2);
log.info("共有学校" + select1.size() + "个");
// 提取学校名称和链接
if (select1.size() > 0) {
for (Element element : select1) {
String text = element.text();
String value = element.attr("href");
log.info("获取到学校的名称: {}, 学校的连接: {}", text, value);
}
}
}
}
}
运行结果:
INFO 爬取第1页
INFO 共有学校5个
INFO 获取到学校的名称: XXX大学, 学校的连接: http://xxx/school/xxx
...
INFO 爬取第5页
INFO 共有学校4个
INFO 获取到学校的名称: YYY学院, 学校的连接: http://xxx/school/yyy
...
总结:
通过以上示例,我们展示了如何使用 jsoup 进行网页数据的抓取与解析。jsoup 强大的选择器语法和简洁的 API 使得 HTML 解析变得非常高效和便捷。无论是简单的网页抓取,还是复杂的数据提取任务,jsoup 都能胜任。
结语
jsoup 是 Java 开发中处理 HTML 的强大工具。本文介绍了 jsoup 的基础用法,包括如何获取Document
对象、使用选择器语法查找元素以及提取元素内容和属性。通过实际案例,我们进一步展示了 jsoup 在数据抓取中的应用。希望本指南能帮助你更好地掌握 jsoup,提升网页数据处理的效率。
参考资源: