V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐学习书目
Learn Python the Hard Way
Python Sites
PyPI - Python Package Index
http://diveintopython.org/toc/index.html
Pocoo
值得关注的项目
PyPy
Celery
Jinja2
Read the Docs
gevent
pyenv
virtualenv
Stackless Python
Beautiful Soup
结巴中文分词
Green Unicorn
Sentry
Shovel
Pyflakes
pytest
Python 编程
pep8 Checker
Styles
PEP 8
Google Python Style Guide
Code Style from The Hitchhiker's Guide
sjmcefc2
V2EX  ›  Python

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

  •  
  •   sjmcefc2 · 2018-05-01 19:43:18 +08:00 · 2753 次点击
    这是一个创建于 2431 天前的主题,其中的信息可能已经有所发展或是发生改变。

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

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

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

    9 条回复    2018-05-03 14:40:39 +08:00
    noe132
        1
    noe132  
       2018-05-01 20:48:40 +08:00 via Android
    字符检测不是 100%确定的。
    是根据文件的字节在各种编码情况下的概率。

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

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

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

    如果这样的效果仍然不能被接受(也就是说,被误判为三种当中的另外两种编码),你可以考虑根据实际情况调整三种编码的权重。或者拟定一个常用字范围,如果看起来「像乱码」(生僻字),再试着有另一种解码器。
    shootsoft
        8
    shootsoft  
       2018-05-02 18:42:41 +08:00 via iPhone
    你要是知道编码检测的原理就没这个疑问了🤓
    sjmcefc2
        9
    sjmcefc2  
    OP
       2018-05-03 14:40:39 +08:00
    @Arnie97 感谢。非常好的思路。看起来这种判断还是挺复杂的,最终还是免不了肉眼“看”
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   5388 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 25ms · UTC 07:37 · PVG 15:37 · LAX 23:37 · JFK 02:37
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.