response.encoding = 'utf-8' 有时加剧乱码,因覆盖 requests 自动识别的 apparent_encoding(如 GBK 页面强制 UTF-8 解码会错读字节);应优先依据 headers charset、验证 apparent_encoding、结合 content 二进制特征手动 decode。
为什么
有时反而让乱码更严重
因为很多网页实际编码不是 UTF-8,硬设会覆盖 requests 自动识别的结果。比如 GBK 编码的中文页面,强制设成
后,
解码时就会把两个字节当一个 UTF-8 字符处理,直接崩出 或其他乱码。
requests 默认用
(基于 chardet 探测)做初始解码,这个值通常比硬写
更靠谱——但也不是万能的,尤其遇到 meta 标签缺失、BOM 混乱或压缩传输时。
优先看
,如果有
这类明确声明,就按它来
没声明时,先打印
和
(二进制前100字节),确认探测是否合理
若探测结果是
但页面明显乱码,大概率是 GBK/GB2312,可试
为啥经常不准,怎么补救
chardet 的探测逻辑依赖字节分布统计,对短文本、无特征内容(比如纯数字 ID 列表)、含大量英文的中文页,容易误判为
或
。更麻烦的是,某些网站返回的
声明和实际 body 编码不一致,requests 会优先信 header,导致
被绕过。
永远别只信
,一定要结合
二进制内容肉眼判断:用
看有没有常见 GBK 特征字节(如
、
)
手动 decode 时用
或
,避免解码中断;之后再用正则或字符串特征(如中文字符占比)反推是否成功
对已知固定站点,直接记下它的编码(比如某政府网站永远用
),写死比自动推断稳
requests 中
和
的区别在哪
是 requests 封装好的字符串,内部调用了
。一旦你改了
,
就会跟着变;但
始终是原始 bytes,不受影响——这是调试乱码的关键。
Python 3.14.3
微软官方的 Python 扩展,是 VS Code 安装量最高的扩展(209M+)。集成 IntelliSense(通过 Pylance)、调试(通过 Python Debugger)、代码检查、格式化、重构和单元测试等功能。支持 Jupyter Notebook、虚拟环境管理和多 Python 版本切换。
下载
立即学习
“
Python免费学习笔记(深入)
”;
调试时永远先 print
,而不是直接 print
如果
正常,但
乱码,说明
设错了,或者没设对时机(必须在访问
前设)
用
可保留无法解码的字节,后续还能转回 bytes 处理,适合需要二次编码的场景
遇到 gzip 压缩响应时,编码问题会更复杂吗
会。requests 默认自动解压
,但解压后的 bytes 才是真正要解码的内容。如果服务器 header 声明了错误 charset(比如
,但实际 body 是 gzip 压缩的 GBK),requests 仍会按 header 设置
,导致解码失败。
检查
,确认是否被压缩;若为
,确保 requests 版本 ≥ 2.25.0(旧版有解压后 encoding 丢失 bug)
手动控制解压:设
绕过 gzip,拿到原始压缩流后自己解压再 decode,可控性更高
某些小众编码(如
)requests 不支持,必须用
+
手动处理
乱码本质是 bytes 到 str 的映射错误,关键不在“选哪个编码”,而在于验证当前 bytes 真实属于哪种编码——这一步跳过,后面全白搭。
response.encoding = 'utf-8'utf-8response.textresponse.apparent_encodingutf-8response.headers.get('content-type')charset=gbkresponse.apparent_encodingresponse.content[:100]utf-8response.content.decode('gbk', errors='ignore')apparent_encodingasciiutf-8content-typeapparent_encodingapparent_encodingresponse.contentresponse.content[:50].hex()c4e3b9a3errors='replace''ignore'gb2312response.textresponse.content.decode()response.textresponse.content.decode(response.encoding)response.encodingtextresponse.contentresponse.content[:200]response.textresponse.content.decode('gbk')response.textresponse.encoding.textresponse.content.decode('utf-8', errors='surrogateescape')gzipcharset=utf-8encodingresponse.headers.get('content-encoding')gzipheaders={'Accept-Encoding': 'identity'}hz-gb-2312response.contentcodecs.decode(...)