手头处理一个文本,整体上来说是 utf-8 的,但每一行中不同的段可能是其他的中文编码,也就是中文的这几个编码 gb2312,gbk,big5 等。
发现循环进行 chardet 时候,单汉字容易被判断为 TIS-620,比如“翠”“纠”;但诡异的是,如果是单独进行检测,这样的单汉字又会被正确的判定为 utf-8。不太明白这其中的道理。单汉字常被解码成 ibm866,ibm855,iso-8859-2,koi8-r 等奇葩编码。
这样复杂的文本,如何才能正确解码呢?
1
noe132 2018-05-01 20:48:40 +08:00 via Android
字符检测不是 100%确定的。
是根据文件的字节在各种编码情况下的概率。 简单说假设 utf8 某个字节只可能是 00 - CC,但是这个字节是 DD,那么基本可以确定这个文件不是 utf8。 另外一个角度,这个文件的字节有 90%都符合一个正常 utf8 文件的字节排列,那么很大概率这个文件就是 utf8。 确定文件编码除了含 bom 的 utf8,包含有明确特征的文件头,其他格式基本就是靠猜。 |
2
sjmcefc2 OP @noe132 这样就会在不同的检测时点,检测结果不一样?为什么总觉得猜应该猜的一致才对呢?
另外,既然是猜,我也知道这个文件里面没有 ascii,utf-8,gbk,gb2312,gb10830,big5 之外的编码,是不是可以武断一点,如果发现 chardet 检测出上述编码之外的,我就用 utf-8 去碰运气? |
3
billlee 2018-05-01 22:41:00 +08:00
@sjmcefc2 #2 chardet 是根据概率分布来识别的,你用单个字符做输入完全没有意义,每次结果不一样说明 chardet 用了随机算法。
如果自己识别,可以先用 UTF-8 解码,因为非 UTF-8 编码的数据按 UTF-8 解码,大概率会解码失败。对解码失败的段落再另行处理吧 |
4
sjmcefc2 OP @billlee 那多少个字符会比较准?
中文字符的话,应该 gbk,gb2312,gb10830,big5 就这几个了吧。会不会出现两种或者多种都能解码的,但解码只有一个正确的? |
5
noe132 2018-05-02 02:44:00 +08:00 via Android
当然 utf8 是 ASCII 的超集,gbk 是 gb2132 的超集。
解码都能解码,最明显的就是 gbk 当 utf8 来解码就会乱码。但是电脑不知道是否乱码,只有人能看出来 |
6
sjmcefc2 OP @noe132 这个乱码判断真的就只能是判断图像了?我这个文本太奇葩了,一行里面掺杂太多不同的编码。chardet 有没有可能不适用随机算法?让每次的输出都相同?大规模判断就有问题,单个测试就能正确解码,这个现象很奇葩。
|
7
Arnie97 2018-05-02 18:37:41 +08:00 via Android
虽然你在 V2EX 问过好多遍了,但是这次的需求说的更为清楚,所以我可以重新回答一下。
这次你说清楚了你的解码内容只有汉字。那么,不妨直接调用 chardet 提供的 big5prober、gb2312prober、utf8prober,然后选择其中置信度最高的一个,这样自然不可能判定为除此三种之外的其他编码。 如果这样的效果仍然不能被接受(也就是说,被误判为三种当中的另外两种编码),你可以考虑根据实际情况调整三种编码的权重。或者拟定一个常用字范围,如果看起来「像乱码」(生僻字),再试着有另一种解码器。 |
8
shootsoft 2018-05-02 18:42:41 +08:00 via iPhone
你要是知道编码检测的原理就没这个疑问了🤓
|