最稳方案是用 htmlagilitypack 解析清洗html,它能正确处理自闭合标签、注释、cdata及不规范结构;安装后调用 documentnode.innertext 获取纯文本,或遍历 //text() 节点并用 htmlentity.deentitize 处理实体。
用 htmlagilitypack 解析并剥离标签最稳
直接上结论:别手写正则删 <.></.>,它会漏掉自闭合标签、注释、cdata,还可能破坏嵌套结构。用 htmlagilitypack 是 c# 里清洗 html 最可靠的选择。
它把 HTML 当成 DOM 树来处理,能正确识别标签边界、属性、文本节点,哪怕源码不规范(比如没闭合的 <p></p>)也能容错解析。
安装包:Install-Package HtmlAgilityPack
- 调用
doc.DocumentNode.InnerText拿纯文本(保留换行和空格) - 若要保留段落结构,遍历
doc.DocumentNode.SelectNodes("//text()")过滤空白节点 - 遇到
、"等实体,记得用HtmlEntity.DeEntitize()转义
Regex.Replace 清洗简单片段时怎么避坑
如果只是临时处理一段已知结构的 HTML 片段(比如富文本编辑器输出的单行内容),用正则可以快,但必须加约束。
常见错误是写 Regex.Replace(html, "<.>", "")</.> —— 它会跨标签匹配,比如 <div>hello 里会误删到中间。<ul>
<li>改用非贪婪 + 单行模式:<code>Regex.Replace(html, "]*>", "", RegexOptions.Singleline)
<!--.*?--> 和 CDATA: 需提前替换掉<script>alert("<div>")</script> 会被切碎为什么 WebUtility.HtmlDecode 不等于“去标签”
新手常混淆解码和清洗:WebUtility.HtmlDecode 只负责把 < 变成 ,它不删标签,也不处理任何 <code><xxx></xxx> 结构。
如果你拿到的是双重编码字符串(比如 <div>test</div>),得先 decode 两次,再进清洗流程。
- 一次
HtmlDecode→<div>test</div> - 二次
HtmlDecode→<div>test</div> - 此时才能交给
HtmlAgilityPack或正则处理
抓取后立刻清洗?注意编码和 BOM 干扰
网页响应体里的 UTF-8 BOM(\uFEFF)或乱码字符(如 \u0000)会导致 HtmlAgilityPack 解析失败,报错 System.Xml.XmlException: Data at the root level is invalid。
不是 HTML 写错了,是字节流没对齐。
- 用
Encoding.UTF8.GetString(bytes)前,先用Encoding.UTF8.GetPreamble().Length跳过 BOM - 或统一用
new StreamReader(stream, Encoding.UTF8, detectEncodingFromByteOrderMarks: true) - 若源站返回
charset=gb2312,硬用 UTF-8 解码会产出大量 ,清洗结果全是乱码
清洗这事,90% 的问题不出在“怎么删标签”,而出在“输入根本没读对”。











