从网页复制的内容全是 HTML 标签?去标签的正确做法
上周帮人整理一份调研资料,他从某资讯站复制了一段正文粘进 Word,满屏的 <span> <p> ,换行也乱七八糟,原本三行的内容粘成了一坨。他问我有没有现成办法快速清掉,我随口答「正则一行搞定」,写完就被打脸了。
去 HTML 标签这事,看着简单,真做干净没那么容易。下面把踩过的坑记一下。
正则 <[^>]+> 为什么不够用
搜「JS 去除 HTML 标签」,第一页基本都长这样:
const text = html.replace(/<[^>]+>/g, '')
逻辑很直白:匹配一个 <,后面跟一串不是 > 的字符,遇到 > 收尾,整体替换为空。常规段落标签能去掉,但两类内容会漏。
第一类是 <script> 和 <style> 的内部文本。HTML 标签是结构,script 和 style 里装的却是代码本身。你把 <script> 和 </script> 两个标签去掉了,中间那一段 JS 源码纹丝不动地留在了正文里。
<script>
ga('send', 'pageview', { title: '首页' })
</script>
正则跑完,ga('send', 'pageview', { title: '首页' }) 这一行会原封不动出现在你的「干净文本」里。<style> 同理,CSS 规则会残留在结果里。
第二类是属性值里带 > 的情况。比如:
<a href="#" data-info="a > b > c">比较</a>
正则 <[^>]+> 会在属性里的第一个 > 处提前收尾,后面的 b > c">比较</a> 全留下来,结果比清之前还乱。
更稳妥:DOMParser + textContent
把脏活扔给浏览器。浏览器本来就是解析 HTML 的专家,嵌套结构、属性里的尖括号、自闭合标签它都认得。DOMParser 解析完之后取 textContent,就能拿到标签全去掉之后的纯文本。
function stripHtml(html) {
const doc = new DOMParser().parseFromString(html, 'text/html')
return doc.body.textContent
}
这段代码会先把 <script> <style> 当作真实节点处理,textContent 取值时天然跳过这两个标签的内部内容(因为它们属于非文本节点)。属性里那个 a > b > c 也不会出问题,浏览器按属性值解析,不会误认为标签结尾。
Node 环境没有 DOMParser,可以上 jsdom 或者用更轻的 htmlparser2。思路一致,不要自己写正则去匹配标签。
别忘了 HTML 实体
去完标签还有一关。HTML 里很多字符是用实体写的: 是不换行空格,& 是 &,< 是 <," 是双引号,' 是单引号。标签去了,这些字面量还留在文本里。
实际效果是这样:
输入:<p>单价 < 100 元</p>
仅去标签后:单价 < 100 元
你期望的:单价 < 100 元
解码实体的常用清单:
| 实体 | 字符 |
|---|---|
| 不换行空格(U+00A0) |
& | & |
< | < |
> | > |
" | " |
' | ' |
好消息是用 DOMParser 走一遍的话,textContent 已经顺手帮你把实体解码了,不用自己再写一张替换表。这是把活交给浏览器的另一个理由。
全角空格和换行符的归一化
实体解决完还有空白。两类特别坑。
第一类是全角空格 (U+3000)。中文排版里常用,普通的 /\s/ 在某些引擎下不一定匹配它,需要单独写:/ /g。漏掉它的话,你清完的文本里会留下一个个看不见但确实占位置的空格,肉眼对不上原因。
第二类是换行符。Windows 是 \r\n,老 Mac 是 \r,Unix/Linux 是 \n。同一段文本里混着几种换行很常见,尤其是经过多次复制粘贴之后。统一成 \n 是基本操作:
text.replace(/\r\n/g, '\n').replace(/\r/g, '\n')
换行统一之后,再合并多余的空行:
text.replace(/\n{3,}/g, '\n\n')
这样原本七零八落的段落会回到正常的「段间一空行」结构。
实操
不想自己敲这些代码,直接把内容丢到 UPTools 文本清理工具 里。勾选「清除 HTML 标签」会走 DOMParser + 实体解码 + 空白归一化,全角空格和换行也一并处理,能一次出干净文本。所有运算都在浏览器本地,不传服务器。
三句话总结
纯 <[^>]+> 正则去标签会留下 <script> <style> 的内部代码,属性值里的 > 也会让它提前收尾。把 HTML 交给 DOMParser 解析再取 textContent,嵌套、属性尖括号、HTML 实体浏览器会一并替你处理干净。剩下的全角空格 和三种换行符 \r\n / \r / \n 单独归一化,连续空行再合并,整段文本才算真正干净。
相关文章