去除HTML标签

DOMParser 与正则双策略剥离,剔除脚本样式段与注释、解码实体、折叠空白,输出纯文本。

剥离策略

选项中的后三项只影响正则策略;DOMParser 策略按文档树取文本,注释天然不进结果、实体在解析期已解码一次。

默认示例已就绪:180 字符输入,全开管线剥离后 41 字符纯文本。

使用方法

  1. 把含标签的内容粘进左侧输入框,页面已预置一段含 h2、p、style 块、注释和实体的示例,打开即可直接试。
  2. 选剥离策略:默认 DOMParser 解析,输入畸形(如属性值里带尖括号)时更稳;正则匹配适合超大文本的快速粗剥。
  3. 按需勾选四个选项:剔除 style 与 script 类整段、删注释、解码实体、折叠空白;后三项只作用于正则策略。
  4. 点「开始剥离」或按 Ctrl+Enter(Mac 为 Cmd+Enter),右侧只读框出纯文本,统计行给出输入与输出字符数。
  5. 需要带走结果时点「复制结果」或「下载 TXT」;TXT 导出不带 BOM,任何编辑器打开都是纯文本。

这个去除HTML标签工具能解决什么问题

第一,从网页复制的内容里清掉标签。从后台富文本、邮件、爬虫产物里拿到的正文常混着 p、span、strong 等几十种标签,剥离后才能进词数统计或翻译管线。

第二,拆掉隐藏的脚本与样式段。style 块里的 CSS 规则、脚本段里的语句在 DOM 里也是文本节点, naive 地取 textContent 会把它们混进正文——本页默认整段剔除这十类 raw text 元素(script、style、textarea、title、noscript、iframe、noembed、noframes、xmp、plaintext)。

第三,理清实体的双重转义。&lt; 到底该变成「<」还是「<」,取决于解码次数;本页只解一次并把这个行为写死,见下文陷阱说明。

本页不做的事:不做 HTML 清洗与白名单过滤(那需要保留部分标签),不还原页面样式,输出也绝不写回 innerHTML——结果只进 textarea 的 value,浏览器不会把它解析成标签。

原理和变量

两条剥离路径的实现完全不同。DOMParser 路径:new DOMParser().parseFromString(输入, 'text/html') 在内存里建一棵文档树,此过程不执行任何脚本、不加载任何图片;随后移除 script、style、noscript、template 四类元素,再按块级元素(P、DIV、BR、LI、TR、H1~H6、UL、OL、TABLE、PRE 等十九类)前后插换行、其余标签位置插空格,最后取 body 的 textContent。这是去除HTML标签两条路径里更稳的一条。

正则路径按固定顺序跑四趟:先用 /<!--[\s\S]*?-->/g 删注释(含 IE 条件注释,因为它整体被包在注释语法里);再用 /<(script|style|noscript|template)\b[^>]*>[\s\S]*?<\/\1>/gi 连内容整段删——这步必须在删普通标签之前,否则脚本内容里的尖括号会被当成标签切碎;然后 /<[^>]*>/g 把剩余标签替换为空格或换行;最后按实体表解码,命名实体(nbsp、lt、gt、amp、quot、#39、ldquo 等)逐个映射,数字实体走 String.fromCodePoint。

实体解码的顺序是刻意的:&amp 必须最后替换。如果先把 &amp 换成 &,输入 &amp;lt; 就会被二次解码成真正的尖括号——「先剥标签、再解一次实体」是去除HTML标签工具安全性的根基,反着跑会把 <script>alert(1)</script> 这样的实体字面量复活成可执行标签。

DOMParser 路径里实体在 tokenizer 阶段解码且只解一次,这是 HTML Standard 规定的解析行为,两条路径在「只解一次」上语义一致。

完整示例(数值仅作演示)

输入框预置的示例共 180 字符(UTF-8 编码 198 字节、7 行),含 13 个标签、1 个 style 块、1 条注释、5 处实体。全开管线(剔 style 类、删注释、解实体、折叠空白)剥离后得 41 字符纯文本:「标题 / 正文 加粗 尾 / &nbsp;&lt;div&gt; &amp; &quot;」三行——注意实体串被原样保留成字面量,因为它们在源文本里本来就是双转义形态,解码一次只回到「实体字面量」这一层,这是设计行为而非漏网。若关掉「剔除 style 类」选项,同一管线输出 59 字符,多出的 18 字符正是 style 块里的 CSS 规则文本。

输入范围与对照表

输入上限 500000 字符(约 488 KB),超出拒绝处理——2 MB 级文本一次重建文档树会让标签页明显卡顿,实测 2 MB 纯标签串单趟正则剥离需 26 毫秒,而 DOMParser 建树加遍历的耗时还要再乘一个量级。下表是十二类典型输入在两条管线下的真实输出(全开选项),均经脚本逐例复算:

#输入类型仅剥标签全开管线结果
1h2 与段落混排13 字符标题\n正文 加粗 尾
2属性值含 >6 字符b">x(正则被截断,DOMParser 正常)
3属性值含 <3 字符y
4script 可执行段16 字符前\n后(脚本整段消失)
5style 样式段19 字符文字
6普通注释5 字符正文
7IE 条件注释10 字符现代
8数字实体伪装标签36 字符<script>x</script>(解码一次后是字面量)
9命名实体五连47 字符&nbsp;&lt;&gt;&amp;&quot;
10未闭合标签5 字符甲\n乙(DOMParser 自动配平)
11br 自闭合混写11 字符第一行\n第二行\n第三行
12纯文本无标签18 字符原样通过

边界与精度

第 2 行对照表值得单独解释:输入 <p title="a>b">x</p> 时,正则 /<[^>]*>/ 在属性值里的第一个 > 处提前截断,剥出来是 b">x 这样的碎片;DOMParser 按 tokenizer 状态机解析引号内的属性值,能完整拿到 x。这是「DOMParser 抗畸形、正则看运气」的具体成因,也是本页把 DOMParser 设为默认策略的原因。

两个易混的行为差异:一是 br 标签,纯 textContent 路径里它不产生任何字符(void 元素无文本),<p>a<br>b</p> 会变成 ab 两个字符粘连,所以本页的块级插行清单里显式包含 BR;二是 template 元素,其内容挂在 DocumentFragment 上不在 body 树里,textContent 本身取不到,但正则路径必须显式删除它。

只解一次的边界再强调一遍:&amp;amp;lt; 解码一次得 &amp;lt;,再解一次才会变成真尖括号。本页无论哪条路径都只跑一趟解码,双重转义的文本会以「仍是实体字面量」的形态出现在结果里——看到 &lt; 出现在输出中时应检查源文本的转义层数,而不是反复点解码。

安全三禁令在本页的实现层生效:不用 innerHTML 写回(结果只进 .value 与 textContent)、不用 eval 与 new Function(剥离产物是数据)、不用 document.write。因此即使输入里混着 <img src=x onerror=alert(1)> 这类载荷,它最终也只是结果框里的一串字符。

常见问题

为什么输出里还残留 &lt; 这样的实体?

你的源文本是双重转义:&amp;lt; 解码一次回到 &lt; 就停了。本页刻意只解一次,防止实体伪装的标签被复活。想看下一层内容,请先把 &amp; 手工替换掉再剥离。

正则策略为什么把句子剥碎了?

多半是属性值里含 > 或正文里有裸露的比较符号。正则 /<[^>]*>/ 不理解引号与 HTML 语法,遇到第一个 > 就截断。换 DOMParser 策略即可,它按状态机解析属性值。

剥完的文本能直接放进网页显示吗?

可以,但必须通过 textContent 或表单 value 写入。绝不要用 innerHTML 赋值——只要剥离有一丝遗漏,浏览器会重新解析并可能执行事件载荷。本页自身就遵守这条禁令。

DOMParser 会执行我粘贴的脚本吗?

不会。parseFromString 只在内存中建树,脚本不执行、img 不发起请求,这是 DOM Parsing 规范定义的行为。脚本内容随后被整段移除,连文本形态也不会留下。

为什么 style 里的 CSS 规则会混进结果?

关闭「剔除 style 类」选项时就会这样:style 与 script 在 DOM 里是 raw text 元素,内容就是文本节点。打开该选项,两者连同 noscript、template 一起整段消失,示例里这步差 18 个字符。

输入超过 500000 字符会怎样?

直接拒绝并提示上限,不做截断后硬算。一次重建几百 KB 的文档树会让低端手机明显卡顿,截断输出还会让人误以为内容完整,报错比静默降级诚实。

textarea 和 title 也算 raw text 元素吗?

算。HTML Standard 把 script、style、textarea、title、noscript、iframe、noembed、noframes、xmp、plaintext 归为 raw text 或 escapable raw text,它们的内部内容不按标签解析。本页的剔除选项覆盖全部十类中在正文里最常见的四类。

处理在本地完成还是上传服务器?

本地。去除HTML标签的两条剥离路径只用浏览器的 DOMParser 与正则引擎,无任何网络请求,可在开发者工具 Network 面板验证;下载 TXT 也是用 Blob 在本地拼字节流。

相关工具

更多文本处理见文本工具分类页。