直接调用get_text()会残留乱码和空行,因其仅剥离HTML标签而不识别语义噪声,页脚、广告、script注释及零宽字符(如\u200b)、BOM(\ufeff)、连续换行等均被原样保留;需先清理DOM结构、再分三步正则清洗文本。

为什么直接 get_text() 会残留乱码和空行
因为 get_text() 只剥离 HTML 标签,不识别语义噪声:页脚、广告 div、script 注释里的文本全被保留;零宽字符(如 \u200b)、BOM(\ufeff)、连续换行、不可见 Unicode 符号(如 \u2028)都会原样输出。你看到的“空行”其实是多个 \n + 零宽空格混在一起的结果。
先用 BeautifulSoup 剥离干扰区块再提取
别对整个 body 调用 get_text(),先清理 DOM 结构:
-
soup.find_all(['script', 'style', 'nav', 'footer', 'aside', 'header', 'noscript'])批量.decompose() - 优先定位正文容器:
soup.find('article')或soup.select_one('.post-content, .entry-content, #content') - 若无明确容器,用启发式方法:
soup.find(lambda tag: tag.name == 'p' and len(tag.get_text()) > 100)找最长段落父节点
用正则批量清洗文本中的乱码字符
提取出纯文本后,必须做三类清洗,顺序不能错:
- 去零宽与 BOM:
re.sub(r'[\u200b\u200c\u200d\ufeff\u2028\u2029]+', '', text) - 合并空行:
re.sub(r'\n\s*\n', '\n\n', text)(保留段落间距,删掉中间夹杂的空格/制表符) - 统一空白符:
re.sub(r'[ \t\r\f\v]+', ' ', text).strip()(注意不是\s,避免误吞换行) - 删非 ASCII 控制字符(可选):
re.sub(r'[\x00-\x08\x0b\x0c\x0e-\x1f\x7f]', '', text)
遇到混合编码乱码时怎么救?
如果清洗后仍有“”或“???”,说明原始字节流已损坏,此时不能靠字符串替换,得回退到字节层处理:
- 用
response.content(而非response.text)获取原始字节 - 显式解码并容错:
text = response.content.decode('utf-8', errors='ignore') - 若怀疑是 GBK 编码:
text = response.content.decode('gbk', errors='ignore') - 更稳的做法:
import chardet; enc = chardet.detect(response.content)['encoding']; text = response.content.decode(enc or 'utf-8', errors='ignore')
真正难的不是写几行正则,而是判断哪些“乱码”其实是业务需要保留的符号(比如 emoji、数学符号、日文假名),哪些是必须剔除的损坏字节——清洗前最好先抽样看原始 response.content[:512] 的十六进制表示。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











