读取时报 UnicodeDecodeError
pd.read_csv 默认按 UTF-8 读取。如果文件是用 GBK 保存的(例如 Excel 另存的“CSV(逗号分隔)”、银行流水或旧系统的导出文件),就会报 UnicodeDecodeError: 'utf-8' codec can't decode byte 0xd6,而 D6 D0 正是 GBK 中的“中”。这时指定编码即可:
pd.read_csv('data.csv', encoding='gb18030'):GB18030 包含 GBK 和 GB2312 的全部字符,生僻字也不会出错,最稳妥。encoding='gbk'大多数情况下也可以,但遇到少数 GBK 没有收录的字时会报错。- 文件开头有 BOM 时用
encoding='utf-8-sig',否则第一个列名前会多出一个看不见的\ufeff,按列名取值时报KeyError。 - 不知道是什么编码?把文件拖进 Mojibuster,它会自动识别编码,并保存为 UTF-8。
'gbk' codec can't decode:open() 的默认编码
反过来的错误同样常见:open('data.txt') 不写 encoding 时,Python 在 Windows 上使用系统编码,简体中文 Windows 上就是 GBK(cp936)。读取 UTF-8 文件时会报 UnicodeDecodeError: 'gbk' codec can't decode byte …,或者不报错,却读出 浣犲ソ。所以请始终写上 encoding='utf-8',或者设置环境变量 PYTHONUTF8=1。根据 PEP 686,今后的 Python 版本会默认使用 UTF-8。
to_csv:用 Excel 打开是乱码
df.to_csv('export.csv') 写出的是不带 BOM 的 UTF-8。中文版 Excel 双击打开时会按 GBK 读取,中文就成了乱码。改用 encoding='utf-8-sig' 写出带 BOM 的文件,Excel 就能识别 UTF-8。详见 Excel 打开 CSV 乱码。
乱码
濮撳悕,鍩庡競,閲戦 寮犱紵,涓婃捣,1250 鏉庡,娣卞湷,980
修复后
姓名,城市,金额 张伟,上海,1250 李娜,深圳,980
如果乱码已经被保存进文件,单个值可以用 s.encode('gbk').decode('utf-8') 还原,但只要有一个单元格本来就是正确的,这个方法就会出错。更简单的办法是先用 Mojibuster 修复文件,再用 pandas 读取。
requests 爬虫中文乱码
requests 根据响应头 Content-Type 决定 response.text 的编码。如果文本响应的头部没有写字符集,它会按 ISO-8859-1 解码:UTF-8 网页变成 ä½ å¥½,GBK 网页变成 ÄãºÃ。先设置 response.encoding = response.apparent_encoding(或直接写 'utf-8'、'gbk'),再读取 response.text。
如果读写时用过 errors='replace' 或 encoding_errors='replace',无法转换的字已经变成 ? 或 �,原来的信息丢失了,无法恢复。更多乱码类型见 乱码是什么。
常见问题
gbk、gb2312、gb18030 该用哪个?
读取时用 gb18030。它包含 GBK 和 GB2312 的全部字符,能读的文件最多。给旧系统写文件时,按对方的要求选择。
有修复乱码的 Python 库吗?
有,例如 ftfy,不过它主要针对西文乱码。处理单个文件又不想写代码时,用 Mojibuster 更快,保存前还能看到每一处改动。
分隔符和数字会被改动吗?
不会。Mojibuster 只修改乱码的字符,逗号、引号和换行都保持原样。