使用 Python 的 chardet 检测字符,为何会发生同一字符串检测结果并不相同的情况?

2018-05-01 19:43:18 +08:00
 sjmcefc2

手头处理一个文本,整体上来说是 utf-8 的,但每一行中不同的段可能是其他的中文编码,也就是中文的这几个编码 gb2312,gbk,big5 等。

发现循环进行 chardet 时候,单汉字容易被判断为 TIS-620,比如“翠”“纠”;但诡异的是,如果是单独进行检测,这样的单汉字又会被正确的判定为 utf-8。不太明白这其中的道理。单汉字常被解码成 ibm866,ibm855,iso-8859-2,koi8-r 等奇葩编码。

这样复杂的文本,如何才能正确解码呢?

2735 次点击
所在节点    Python
9 条回复
noe132
2018-05-01 20:48:40 +08:00
字符检测不是 100%确定的。
是根据文件的字节在各种编码情况下的概率。

简单说假设 utf8 某个字节只可能是 00 - CC,但是这个字节是 DD,那么基本可以确定这个文件不是 utf8。
另外一个角度,这个文件的字节有 90%都符合一个正常 utf8 文件的字节排列,那么很大概率这个文件就是 utf8。

确定文件编码除了含 bom 的 utf8,包含有明确特征的文件头,其他格式基本就是靠猜。
sjmcefc2
2018-05-01 22:02:52 +08:00
@noe132 这样就会在不同的检测时点,检测结果不一样?为什么总觉得猜应该猜的一致才对呢?
另外,既然是猜,我也知道这个文件里面没有 ascii,utf-8,gbk,gb2312,gb10830,big5 之外的编码,是不是可以武断一点,如果发现 chardet 检测出上述编码之外的,我就用 utf-8 去碰运气?
billlee
2018-05-01 22:41:00 +08:00
@sjmcefc2 #2 chardet 是根据概率分布来识别的,你用单个字符做输入完全没有意义,每次结果不一样说明 chardet 用了随机算法。
如果自己识别,可以先用 UTF-8 解码,因为非 UTF-8 编码的数据按 UTF-8 解码,大概率会解码失败。对解码失败的段落再另行处理吧
sjmcefc2
2018-05-01 23:03:37 +08:00
@billlee 那多少个字符会比较准?
中文字符的话,应该 gbk,gb2312,gb10830,big5 就这几个了吧。会不会出现两种或者多种都能解码的,但解码只有一个正确的?
noe132
2018-05-02 02:44:00 +08:00
当然 utf8 是 ASCII 的超集,gbk 是 gb2132 的超集。
解码都能解码,最明显的就是 gbk 当 utf8 来解码就会乱码。但是电脑不知道是否乱码,只有人能看出来
sjmcefc2
2018-05-02 09:07:14 +08:00
@noe132 这个乱码判断真的就只能是判断图像了?我这个文本太奇葩了,一行里面掺杂太多不同的编码。chardet 有没有可能不适用随机算法?让每次的输出都相同?大规模判断就有问题,单个测试就能正确解码,这个现象很奇葩。
Arnie97
2018-05-02 18:37:41 +08:00
虽然你在 V2EX 问过好多遍了,但是这次的需求说的更为清楚,所以我可以重新回答一下。

这次你说清楚了你的解码内容只有汉字。那么,不妨直接调用 chardet 提供的 big5prober、gb2312prober、utf8prober,然后选择其中置信度最高的一个,这样自然不可能判定为除此三种之外的其他编码。

如果这样的效果仍然不能被接受(也就是说,被误判为三种当中的另外两种编码),你可以考虑根据实际情况调整三种编码的权重。或者拟定一个常用字范围,如果看起来「像乱码」(生僻字),再试着有另一种解码器。
shootsoft
2018-05-02 18:42:41 +08:00
你要是知道编码检测的原理就没这个疑问了🤓
sjmcefc2
2018-05-03 14:40:39 +08:00
@Arnie97 感谢。非常好的思路。看起来这种判断还是挺复杂的,最终还是免不了肉眼“看”

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/451260

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX