JSoup 是最可靠HTML解析库,自动修复畸形HTML;提取文本需先parse再body().text(),删script/style后再text();Hutool HtmlUtil轻量但容错弱;禁用正则清洗HTML;清洗后须校验隐藏字符。

用 JSoup 解析并清洗 HTML 内容
JSoup 是 Java 生态中最可靠、最容错的 HTML 解析库,它不依赖浏览器环境,能自动修复 malformed HTML(比如缺失闭合标签、嵌套错误),适合做服务端内容清洗。直接调用 text() 会递归提取所有文本节点,但会丢弃结构信息;若需保留部分语义(如段落分隔),应遍历 Element 节点手动处理。
常见错误:用 Document.body().text() 提取时,如果原始 HTML 没有 <body> 标签(纯片段),会返回空字符串——正确做法是先用 Jsoup.parse(html) 得到完整 Document,再调用 document.body().text() 或 document.text()。
- 对含 script/style 的页面,
document.select("script, style").remove()必须在text()前执行,否则脚本内容也会被当作文本提取 - 实体字符(如
)会被自动转义,无需额外调用Jsoup.unescapeEntities() - 若 HTML 来自不可信来源,务必启用
Whitelist过滤,例如Jsoup.clean(dirtyHtml, Whitelist.none())防 XSS
Hutool 的 HtmlUtil 做轻量级清洗
如果你项目已引入 Hutool,且只需简单去标签、删广告块或过滤属性,HtmlUtil 是更轻量的选择。它不构建 DOM 树,而是基于正则和字符串操作,速度快但容错弱——遇到严重 malformed HTML(如未闭合的 <div> 嵌套)可能漏删或截断。
典型误用:HtmlUtil.removeHtmlTag(html, "div") 会删除所有 <div> 开始和结束标签及其间全部内容,包括子标签里的文字;若只想清除 div 标签但保留内容,得用 HtmlUtil.unwrapHtmlTag(html, "div")。
立即学习“前端免费学习笔记(深入)”;
-
cleanHtmlTag()适合日志摘要、搜索索引等纯文本场景,但会把换行、空格全压成单空格 -
filter()默认只放行基础标签(p,br,strong等),要保留img需显式加白名单:HtmlUtil.filter(html, Whitelist.simpleText().addTags("img")) - 对含 CDATA 或注释的 HTML,
HtmlUtil不识别它们,可能把<![CDATA[...]]>当普通文本原样留下
避免用正则直接清洗 HTML
正则匹配 HTML 标签(如 <[^>]+>)在多数真实场景下会失效:无法处理嵌套、属性值含 >(如 title="a > b")、注释、CDATA、自闭合标签变体(<br /> vs <br>)。JSoup 和 Hutool 底层都用状态机解析,这才是安全前提。
唯一可接受正则的场景:你**完全控制输入格式**,且 HTML 是严格扁平、无嵌套、无属性的简易标记(例如内部系统生成的 <p>xxx</p><h2>yyy</h2>)。即便如此,也建议先用 Jsoup.parse(html).body().html() 归一化后再正则处理。
- 用
String.replaceAll("<[^>]*>", "")清洗,遇到<img src="a>b.jpg">就会把src="a之后全删掉 - 正则无法区分开始标签
<div class="x">和结束标签</div>,容易误删中间内容 - HTML 实体(
&,")需额外反转义,而 JSoup/Hutool 在解析阶段就已完成
清洗后如何验证是否“干净”
清洗不是终点,得确认输出符合预期。最易被忽略的是:清洗后的文本是否仍含隐藏控制字符、零宽空格、BOM、或不可见 Unicode 符号(如 \u200e LTR mark)。这些字符肉眼不可见,但会影响后续 NLP 分词或数据库存储。
建议在清洗后加一层校验逻辑:
- 用
cleanText.codePoints().anyMatch(cp -> cp > 0x7F && cp < 0x2000)快速扫出非 ASCII 控制符 - 对中文场景,检查是否残留
\u3000(全角空格)或\u2028(行分隔符),它们常被误认为普通换行 - 用
cleanText.trim().isEmpty()判断是否整段被清空——这往往意味着原始 HTML 是 script 标签包裹的 JSON 或 base64 数据,而非可视内容



















