根本原因是requests默认用ISO-8859-1解码,而中文网页多为UTF-8或GBK,且响应头常缺charset或声明错误;应优先用response.content配合apparent_encoding或chardet手动解码。

为什么 requests.get() 返回的 response.text 是乱码?
根本原因不是 HTML 本身“坏”,而是 Python 没有正确识别响应的字符编码。requests 默认用 ISO-8859-1 解码,而多数中文网页声明的是 UTF-8 或 GBK,但响应头里的 Content-Type 缺少 charset 字段,或者声明错误(比如写成 utf-8 而非标准的 utf-8),requests 就不会自动切换。
直接读 response.text 必然乱码;必须改用 response.content 手动解码。
- 永远优先尝试用
response.apparent_encoding—— 它基于 chardet 启发式检测,对 GBK/UTF-8 混合页面比response.encoding更靠谱 - 若
apparent_encoding返回None或明显不对(如Windows-1254),再 fallback 到UTF-8或GBK - 解码失败时加
errors='ignore'或errors='replace',避免脚本中断,但注意会丢字或插
用 BeautifulSoup 自动处理编码比手动更稳吗?
是的,但前提是别跳过原始字节输入。把 response.content 直接传给 BeautifulSoup,它会按以下顺序探测编码:
- HTML meta 标签里的
charset(如<meta charset="UTF-8">) - HTTP 响应头的
Content-Type - 最后才用 chardet 推测
所以正确写法是:
from bs4 import BeautifulSoup<br>soup = BeautifulSoup(response.content, 'html.parser')而不是
BeautifulSoup(response.text, ...) —— 后者等于把已乱码的字符串再喂给 BS,BS 无力回天。
立即学习“Python免费学习笔记(深入)”;
如果页面 meta 标签缺失或错误(常见于老旧政府网站),可强制指定:
soup = BeautifulSoup(response.content, 'html.parser', from_encoding='GBK')注意参数名是
from_encoding,不是 encoding。
清洗 HTML 时哪些操作会悄悄引入新乱码?
最典型的是用正则或字符串方法二次处理 soup.get_text() 或 str(soup) 的结果后,又转成 bytes 再解码 —— 这会触发 Python 默认编码(通常是 UTF-8),而你刚解出来的文本可能含 GBK 特有字节,导致二次乱码。
- 清洗逻辑尽量在
str层做(如去除多余空白、删 script/style 标签),不要反复 encode/decode - 保存前统一用
.encode('UTF-8')写入文件,别依赖系统 locale - 用
soup.prettify()时显式指定编码:soup.prettify('UTF-8'),否则返回 bytes 但不带编码信息,容易误当 str 处理 - 如果最终要存 CSV,用
pandas.DataFrame.to_csv(..., encoding='UTF-8-sig')避免 Excel 打开乱码
遇到 UnicodeDecodeError: 'gbk' codec can't decode byte 怎么快速定位?
这错误说明你正在用 GBK 解码一段实际是 UTF-8 的字节流(或反之)。别急着改 try/except,先查三处:
- 检查
response.content[:100]的十六进制:UTF-8 中文通常以\xe4\xbb\xa5类三字节开头,GBK 是双字节如\xc4\xe3—— 用response.content[:20].hex()看一眼就清楚 - 打印
response.headers.get('content-type')和response.encoding,确认是否冲突(比如 header 说text/html; charset=gbk,但encoding却是utf-8) - 临时把
response.content写入文件,用 VS Code 或 Notepad++ 手动切换编码打开,肉眼验证哪种能正常显示中文 —— 这比任何库都准
真实场景里,同一网站不同页面可能混用编码,所以清洗脚本不能假设全局统一,每个 response 都得独立探测和处理。



















