在日常的 Java 开发中,我们经常会遇到处理 HTML 内容的场景。无论是做简单的网页数据抓取、处理富文本编辑器提交的内容,还是对文档进行全文索引,从 HTML 中剥离标签、提取纯文本都是一个绕不开的基础需求。
HTML 作为一种标记语言,包含了大量用于控制样式的标签(如 <div>、<span>、<p>)以及脚本代码。如果我们直接使用正则表达式去处理这些嵌套复杂的标签,不仅代码容易出错,而且维护成本较高。
本文将介绍两种处理思路:一种是利用第三方文档处理库(以 Spire.Doc for Java 为例)将 HTML 作为文档解析;另一种是主流的轻量级 HTML 解析器方案。通过对比,帮助开发者根据自身场景做出合理的技术选型。
环境准备:
- JDK 1.8 及以上版本
- Maven 项目管理工具
1. 为什么不能直接用正则表达式?
在处理 HTML 转文本时,正则表达式是最直观的想法,但它存在明显的局限性:
- 无法处理嵌套标签:例如
<div>a<p>b</p>c</div>,正则很难正确匹配层级关系。 - 容易误匹配:标签内的属性、注释、CDATA 等特殊结构容易干扰匹配结果。
- 维护困难:面对不同来源的 HTML(如缺失闭合标签、大小写不一致),正则规则会变得臃肿且脆弱。
因此,推荐使用成熟的解析方案。
2. 方案一:文档转换器方式
该方案借助第三方文档处理库,将 HTML 映射为文档对象模型,然后调用获取文本的方法。
2.1 项目依赖配置
在 pom.xml 中添加如下依赖:
<repositories>
<repository>
<id>com.e-iceblue</id>
<name>e-iceblue</name>
<url>https://repo.e-iceblue.com/nexus/content/groups/public/</url>
</repository>
</repositories>
<dependencies>
<dependency>
<groupId>e-iceblue</groupId>
<artifactId>spire.doc</artifactId>
<version>14.3.1</version>
</dependency>
</dependencies>
注:该库提供免费版和商业版。对于基础的文本提取需求,免费版通常足够。
2.2 核心实现
import com.spire.doc.Document;
import com.spire.doc.FileFormat;
import java.io.FileWriter;
import java.io.IOException;
public class HtmlTextExtractor {
public static void main(String[] args) {
// 1. 实例化 Document 对象
Document document = new Document();
// 2. 加载 HTML 文件(指定格式为 Html)
document.loadFromFile("input.html", FileFormat.Html);
// 3. 提取纯文本内容
String extractedText = document.getText();
// 4. 输出或保存结果
System.out.println("提取的文本内容:\n" + extractedText);
// 可选:保存到 txt 文件
try (FileWriter writer = new FileWriter("output.txt")) {
writer.write(extractedText);
System.out.println("\n文本已成功保存到 output.txt");
} catch (IOException e) {
e.printStackTrace();
}
}
}
代码解析:
Document类通常用于处理 Word 文档,但它同样支持FileFormat.Html格式。加载时,库内部会解析 HTML 标签,将其映射为段落、表格等文档元素。getText()方法遍历文档树,提取所有可见文本,同时跳过控制字符和标签代码。
2.3 处理 URL 网页
如果需要直接抓取线上的网页内容,可以结合 Java 原生的 HttpClient 获取网页源代码后再解析:
import com.spire.doc.Document;
import com.spire.doc.FileFormat;
import java.io.*;
import java.net.URL;
import java.net.URLConnection;
public class UrlTextExtractor {
public static void main(String[] args) {
String urlStr = "https://example.com";
try {
String htmlPath = fetchHtmlFromUrl(urlStr, "temp.html");
Document doc = new Document();
doc.loadFromFile(htmlPath, FileFormat.Html);
String text = doc.getText();
System.out.println(text);
} catch (Exception e) {
e.printStackTrace();
}
}
private static String fetchHtmlFromUrl(String urlString, String savePath) throws Exception {
URL url = new URL(urlString);
URLConnection conn = url.openConnection();
conn.setConnectTimeout(5000);
conn.setRequestProperty("User-Agent", "Mozilla/5.0");
try (BufferedReader reader = new BufferedReader(new InputStreamReader(conn.getInputStream(), "UTF-8"));
FileWriter writer = new FileWriter(savePath)) {
String line;
while ((line = reader.readLine()) != null) {
writer.write(line);
writer.write("\n");
}
}
return savePath;
}
}
注意:解析 URL 时需遵守目标网站的
robots.txt协议及数据获取的合规性要求。
3. 方案二:轻量级 HTML 解析器方式(以 Jsoup 为例)
相比文档转换方式,Jsoup 是专门为 HTML 解析设计的轻量级库,在社区中使用更为广泛。
3.1 依赖配置
<dependency>
<groupId>org.jsoup</groupId>
<artifactId>jsoup</artifactId>
<version>1.17.2</version>
</dependency>
3.2 核心实现
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import java.io.File;
public class JsoupExtractor {
public static void main(String[] args) throws Exception {
// 加载 HTML 文件
Document doc = Jsoup.parse(new File("input.html"), "UTF-8");
// 提取纯文本(自动去除标签)
String text = doc.text();
System.out.println(text);
}
}
Jsoup 的 text() 方法会递归获取所有可见文本,并用空格连接块级元素的内容,输出结果更适合阅读。
3.3 直接解析 URL
Jsoup 内置了网络请求能力,代码更为简洁:
Document doc = Jsoup.connect("https://example.com")
.userAgent("Mozilla/5.0")
.timeout(5000)
.get();
String text = doc.text();
4. 方案对比与适用场景
| 维度 | 文档转换方式(Spire.Doc) | 轻量级解析器(Jsoup) |
|---|---|---|
| 设计定位 | 文档处理(Word、HTML 等) | HTML 解析专用 |
| API 复杂度 | 较高(需了解 Document 模型) | 简单直观 |
| HTML 容错能力 | 较强 | 很强(业界公认) |
| 网络请求 | 需自行实现 | 内置支持 |
| 依赖体积 | 较大(包含文档处理能力) | 小巧(约 500KB) |
| 扩展性 | 可转为 Word 等其他格式 | 聚焦 HTML/CSS 选择器 |
各自的适用场景:
- 文档转换方式:适合需要同时处理 Word 文档和 HTML 文件的场景,或希望统一文档处理逻辑的项目。
- 轻量级解析器:适合纯 HTML 提取、网页抓取、需要按 CSS 选择器提取特定元素内容的场景。
5. 两种方案的共同局限性
无论选择哪种方案,在提取纯文本时都需要注意以下几点:
- 格式信息丢失:提取结果仅包含文本,原 HTML 中的表格布局、字体大小、颜色、图片链接等富媒体信息均会丢失。
- 编码处理:如果 HTML 未正确声明
charset,可能需要手动指定编码,否则可能出现中文乱码。 - 大文件性能:对于数十 MB 的超大 HTML 文件,两种方案的内存占用都会显著上升,建议分块或流式处理。
6. 总结
从 HTML 中提取纯文本是 Java 开发中的常见需求。本文对比了两种可行的技术方案:
文档转换方式以 Spire.Doc for Java 为例,其特点是将 HTML 视为文档对象进行解析,API 封装程度较高,但依赖体积偏大,适合需要统一处理 Word 和 HTML 格式的项目。
轻量级解析器以 Jsoup 为例,它是专门为 HTML 设计的工具,API 简洁、HTML 容错能力强,并且内置了网络请求支持,在社区中使用广泛,是纯文本提取场景下的主流选择。
开发者可以根据项目现有依赖、体积敏感度以及是否需要额外的 HTML 操作(如选择器提取、DOM 修改)来选择合适的方案。如果项目仅需简单的去标签处理,Jsoup 可能是更轻量的选择;如果项目中已经引入了文档处理相关依赖,则可以直接复用文档转换方式。