最直接方式是用re.sub(r']+>', '', text):匹配单个html标签(含开始、结束、自闭合),非贪婪且不跨标签;需预处理nan,清洗后建议配合html.unescape()解码实体。

用 re.sub() 去除字符串中的 HTML 标签最直接
爬虫抓取的文本常混有 <p></p>、<div class="title">、<code><br> 等标签,Pandas 本身不提供 HTML 解析清洗能力,得靠正则或第三方库。最轻量、无依赖的方式是用 Python 内置 re.sub() 配合简单模式匹配。
常见错误是写成 re.sub(r'<.>', '', text)</.>——这会贪婪匹配整个段落(比如 <div>abc</div> 变成空字符串),实际应使用非贪婪模式或更稳妥的通用表达式:
-
re.sub(r']+>', '', text):匹配单个标签(含开始、结束、自闭合),不跨标签干扰内容 - 对含 JS/CSS 的脏数据(如
<script>alert(1)</script>),该正则仍有效,但无法处理标签内属性值里的尖括号(极少见) - 若列中存在
NaN,需先用fillna('')或加isinstance(x, str)判断,否则re.sub报TypeError: expected string or bytes-like object
用 BeautifulSoup 提取纯文本更可靠(尤其嵌套/ malformed HTML)
当 HTML 结构复杂(如 <span><b>价格</b>:</span><span>¥99</span>)或存在未闭合标签(<p>缺货<em>暂无库存</em></p>),正则容易漏或错删。此时 BeautifulSoup 是更稳的选择——它能解析并重建 DOM 树,再调用 .get_text() 安全提取。
实操建议:
- 安装:
pip install beautifulsoup4(无需lxml也能用内置html.parser) - 清洗单列:
df['content'].apply(lambda x: BeautifulSoup(str(x), 'html.parser').get_text() if pd.notna(x) else x) -
.get_text()默认用空格连接文本节点,若需保留换行可传参separator='\n';若要去掉多余空白,后续接.strip().replace('\n', ' ').replace('\r', '').replace('\t', ' ') - 性能注意:比正则慢 5–10 倍,万级以下数据无感,超十万行建议先抽样验证必要性
批量清洗时避免 df.apply() 的隐式类型转换陷阱
用 apply 清洗字符串列时,Pandas 可能因混合类型(如部分单元格是 int、None 或 bytes)自动转成 object dtype,后续做 str.contains() 等操作会报 AttributeError: Can only use .str accessor with string values。
正确做法是显式确保输入为字符串:
- 统一预处理:
df['col'] = df['col'].astype(str)(但会把NaN变成字符串'nan',慎用) - 更安全的清洗函数:
def clean_html(x): if pd.isna(x): return x return re.sub(r']+>', '', str(x)) - 清洗后检查:
df['col'].apply(type).unique()应只含<class></class>和<class></class>(对应 NaN)
特殊字符与编码残留必须额外处理
HTML 中的 、—、" 等实体不会被正则或 BeautifulSoup.get_text() 自动解码,清洗后仍显示为乱码或占位符。
解决方式分两步:
- 用
html.unescape()解码(Python 3.4+ 内置):from html import unescape,然后在清洗函数末尾加unescape(cleaned_text) - 对字节串(如
b' ')需先.decode('utf-8')再 unescape;若原始数据含 GBK 编码残留,得先用chardet探测再 decode - 常见漏点:
'(单引号)、/(斜杠),unescape()全支持,无需单独写规则
<sup>TM</sup> 清成 “TM” 还是 “™”)。动手前先 df['col'].sample(5).tolist() 看真实样本,比套用模板更重要。











