和Python3 Unicode/GBK编码奋斗了半小时感想

想写一个脚本,把某文件夹目录爬成一个HTML,

直接把stdout重定向到了

open(“index.htm”,”w”), 然而编码上总是出问题:

UnicodeEncodeError: 'gbk' codec can't encode character '\u200d' in position 85: illegal multibyte sequence

根据输出来看这些非法字符主要是一些日语和奇奇怪怪的非主流符号(我也不知道我还有这种东西啦)

一想Python3不是号称只要是个str都是Unicode吗,为什么会有gbk乱入呢

一开始是想到Windows的目录默认用的是gbk编码(真是的一点都不国际化),后面想想不对,如果读入的时候就已经是gbk的话,再输出的时候怎么可能gbk解码器报错呢,而且Python3的str和二进制数据流是分开的,既然读取文件列表的函数返回的是str,编码就一定已经是utf8了

后来找到一个不是办法的办法,就是输出前先str.encode(‘gbk’).decode(‘gbk’,’ignore’),看网上的文章说是因为Unicode字符串里面可能含有一些非法字符,无法被gbk转码器(说是转码器,其实只是个key-value map罢了)转换成gbk(这其实是错误的),所以加上ignore参数就能让解码器跳过这些部分(这种方法输出的结果带有很多菱形问号).诶,等一下,gbk?说好的Python3大大国际化都是Unicode呢?

后来,发现,问题出在对”都是Unicode的理解上”. 没错,str全都是Unicode,但是Python3没有保证输出也是用utf8啊,万一输出终端不支持怎么办?(像cmd好像默认是cp936)

知道是输出就好办了,查了查open的文档,发现open缺省的Encoding参数是None,估计就是默认的意思. 改成open(“index.htm”,”w”,-1,”utf8″)就好了(-1也是缺省参数)

成品