Chardet - Python 检测内容编码类型


一、关于 Chardet

Chardet:通用字符编码检测器


检测类型:

  • ASCII、UTF-8、UTF-16(2种变体)、UTF-32(4种变体)
  • Big5、GB2312、EUC-TW、HZ-GB-2312、ISO-2022-CN(繁体和简体中文)E
  • UC-JP,SHIFT_JIS, CP932,ISO-2022-JP(日语)
  • EUC-KR,ISO-2022-KR,Johab(韩语)
  • KOI8-R,MacCyrillic,IBM855,IBM866,ISO-8859-5,windows-1251(西里尔文)
  • ISO-8859-5, windows-1251(保加利亚语)ISO-8859-1, windows-1252,MacRoman(西欧语言)
  • ISO-8859-7, windows-1253(希腊语)ISO-8859-8, windows-1255(视觉和逻辑希伯来语)TIS-620(泰语)

注:我们的ISO-8859-2和Windows-1250(匈牙利语)探头 已暂时禁用,直到我们可以重新训练模型。


安装

需要Python 3.8+。

PyPI安装:

pip install chardet

命令行工具

chardet带有一个命令行脚本,它报告一个或多个文件的编码:

% chardetect somefile someotherfile
somefile: windows-1252 with confidence 0.5
someotherfile: ascii with confidence 1.0

二、用法


1、基本用法

使用通用编码检测器库的最简单方法是使用 的detect功能。


示例:使用detect函数

这个detect函数接受一个参数,一个非Unicode字符串 返回包含自动检测字符编码的字典和 a置信度从01


>>> text = 'haha'
>>> b1 = text.encode('utf-8')
>>> 
>>> chardet.detect(b1)
{'encoding': 'ascii', 'confidence': 1.0, 'language': ''}
>>> chardet.detect('你好'.encode('utf-8'))
{'encoding': 'utf-8', 'confidence': 0.7525, 'language': ''}

import urllib.request
import chardet

rawdata = urllib.request.urlopen('http://yahoo.co.jp/').read()
chardet.detect(rawdata)
{'encoding': 'EUC-JP', 'confidence': 0.99}

2、高级用法

如果您正在处理大量文本,您可以增量调用通用编码检测器库,一旦它有足够的信心报告其结果,它就会停止。

创建一个UniversalDetector对象,然后调用它的feed方法 重复每个文本块。
如果检测器达到最小值 置信度阈值,它会将detector.done设置为True

一旦你用完了源文本,调用detector.close(),它 会做一些最终的计算,以防探测器没有击中它 最小置信度阈值更早。
然后detector.result将是一个 包含自动检测字符编码和 与chardet.detect函数相同 返回)。


示例:增量检测编码
import urllib.request
from chardet.universaldetector import UniversalDetector

usock = urllib.request.urlopen('http://yahoo.co.jp/')
detector = UniversalDetector()

for line in usock.readlines():
    detector.feed(line)
    if detector.done: break
    
detector.close()
usock.close()
print(detector.result)
# -> {'encoding': 'EUC-JP', 'confidence': 0.99}

如果要检测多个文本的编码(例如单独的 文件),您可以重用单个UniversalDetector对象。
只需调用 detector.reset()的开头调用detector.feed 你喜欢多少次就多少次,然后调用detector.close()并检查 用于文件结果的detector.result.结果字典。


示例:检测多个文件的编码
import glob
from chardet.universaldetector import UniversalDetector

detector = UniversalDetector()
for filename in glob.glob('*.xml'):
    print(filename.ljust(60), end='')
    detector.reset()
    for line in open(filename, 'rb'):
        detector.feed(line)
        if detector.done: break
    detector.close()
    print(detector.result)

三、工作机制

这是导航代码本身的简要指南。

首先,你应该阅读一种语言/编码检测的复合方法, 这解释了检测算法以及它是如何导出的。
这将 以后当你偶然发现巨大的字符频率时帮助你 分布表,如big5freq.py和语言模型,如 langcyrillicmodel.py.

检测算法的主要切入点是 universaldetector.py,它有一个类,UniversalDetector
(你可能认为主要切入点是detect函数 chardet/__init__.py,但这实际上只是一个方便的函数 创建一个UniversalDetector对象,调用它,并返回它的 结果。)


有5类编码UniversalDetector处理:

  1. UTF-n带BOM。
    这包括UTF-8,BE和LE UTF-16的UTF-16,以及所有4字节顺序的UTF-32变体。

  2. 转义编码,完全兼容7位ASCII,其中 非ASCII字符以转义序列开头。
    例子: ISO-2022-JP(日文)和HZ-GB-2312(中文)。

  3. 多字节编码,其中每个字符由一个 可变字节数。
    示例:Big5(中文),SHIFT_JIS (日语)、EUC-KR(韩语)和没有BOM的UTF-8

  4. 单字节编码,其中每个字符由一个表示 示例:KOI8-R(俄语)、windows-1255(希伯来语)和 TIS-620(泰语)。

  5. windows-1252,主要用于Microsoft Windows;它的 子集,ISO-8859-1广泛用于传统的8位编码文本。
    Chardet和许多编码检测器一样,默认猜测这个 当没有其他编码可以可靠地建立时。


1、UTF-n 与 BOM

如果文本以BOM开头,我们可以合理地假设文本是 以UTF-8UTF-16UTF-32
(BOM会告诉我们 确切地说是哪一个;这就是它的用途。)

这是内联处理的 UniversalDetector,它立即返回结果,不需要任何 进一步处理。


2、转义编码

如果文本包含可识别的转义序列,该转义序列可能表明 转义编码,UniversalDetector创建一个 EscCharSetProber(在escprober.py中定义)并为其提供 文本。

EscCharSetProber基于模型创建一系列状态机 的HZ-GB-2312ISO-2022-CNISO-2022-JP,和ISO-2022-KR (在escsm.py中定义)。
EscCharSetProber将文本提供给每个 在这些状态机中,一次一个字节。
如果任何状态机结束 向上唯一标识编码,EscCharSetProber立即 将肯定结果返回给UniversalDetector,后者返回它 给调用者。
如果任何状态机命中非法序列,它就是 删除并继续处理其他状态机。


3、多字节编码

假设没有BOM,UniversalDetector检查文本是否包含 任何高位字符。
如果是这样,它会为 检测多字节编码、单字节编码,最后 度假村,windows-1252.

多字节编码探测器MBCSGroupProber(定义于 mbcsgroupprober.py),实际上只是一个管理一组 其他探测器,每个多字节编码一个:Big5GB2312EUC-TWEUC-KREUC-JPSHIFT_JISUTF-8
MBCSGroupProber将文本馈送到这些特定于编码的 探测器并检查结果。
如果探测器报告说它发现了 非法字节序列,从进一步处理中删除(因此, 例如,任何后续调用UniversalDetector.feed 将跳过那个探测器)。
如果探测器报告说它是合理的 相信它已经检测到编码,MBCSGroupProber报告 将此阳性结果发送给UniversalDetector,由其报告结果 给来电者。

大多数多字节编码探测器都是从 MultiByteCharSetProber(定义见mbcharsetprober.py),及 只需连接适当的状态机和分布分析器 让MultiByteCharSetProber做剩下的工作。
MultiByteCharSetProber通过特定于编码的 状态机,一次一个字节,以查找字节序列 表明决定性的积极或消极结果。
同时, MultiByteCharSetProber将文本提供给特定于编码的 分布分析仪。

分布分析仪(每个在chardistribution.py中定义)使用 最常用的字符的特定语言模型。
一旦MultiByteCharSetProber输入了足够的文本 分析仪,它根据 常用字符、字符总数和 特定语言的分布比例。
如果信心足够高, MultiByteCharSetProber将结果返回给MBCSGroupProber, 返回到UniversalDetector,返回到 来电者。

日语的情况比较困难。
单字符分布 分析并不总是足以区分EUC-JPSHIFT_JIS,所以SJISProber(在sjisprober.py中定义)也 使用2个字符的分布分析。
SJISContextAnalysisand EUCJPContextAnalysis(两者均在jpcntx.py及两者中界定 从公共JapaneseContextAnalysis类继承)检查 文本中平假名音节字符的频率。
一次足够了 文本已被处理,他们返回置信度 SJISProber,它检查两个分析器并返回较高的 置信度MBCSGroupProber


4、单字节编码

单字节编码探测器SBCSGroupProber(定义于 sbcsgroupprober.py),也只是一个管理一组的外壳 其他探测器,一个用于单字节编码和 语言:windows-1251KOI8-RISO-8859-5MacCyrillicIBM855IBM866(俄文);ISO-8859-7windows-1253(希腊语);ISO-8859-5windows-1251 (保加利亚语);ISO-8859-2windows-1250(匈牙利语); TIS-620(泰语);windows-1255ISO-8859-8(希伯来语)。

SBCSGroupProber将文本馈送到其中的每一个 encoding+language-specific探测器并检查结果。
这些探测器 都是作为一个类实现的,SingleByteCharSetProber (在sbcharsetprober.py中定义),它将语言模型作为 论点。
语言模型定义了不同的频率 2个字符的序列出现在典型文本中。
SingleByteCharSetProber处理文本并最符合 常用的2字符序列。
一旦有足够的文本 处理后,它根据 常用序列、字符总数和 特定语言的分布比例。

希伯来文作为特例处理。
如果文本看起来是希伯来文 基于2字符分布分析,HebrewProber(定义于 hebrewprober.py)试图区分视觉希伯来语(哪里 源文本实际上逐行“向后”存储,然后 逐字显示,因此可以从右到左阅读)和逻辑 希伯来文(其中源文本按阅读顺序存储,然后 由客户端从右到左呈现)。
因为某些字符是 根据它们是出现在中间还是在 词尾,我们可以对单词的方向做出合理的猜测 源文本,并返回适当的编码(windows-1255for 逻辑希伯来文,或ISO-8859-8视觉希伯来文)。


5、Windows-1252

如果UniversalDetector检测到文本中的高位字符,但 其他多字节或单字节编码探测器都不会返回 自信的结果,它创建一个Latin1Prober(定义于 latin1prober.py)来尝试检测英文文本在一个windows-1252 编码。
这种检测本质上是不可靠的,因为英语 字母在许多不同的编码中以相同的方式编码。
这 区分windows-1252唯一方法是通过常用的 智能引号、卷曲撇号、版权符号和 就像。
Latin1Prober自动将其置信度降低到 如果可能的话,允许更准确的探测者获胜。


四、常见问题

1、什么是字符编码?

当你想到“文本”时,你可能会想到“我在电脑屏幕上看到的字符和符号”。
但是计算机不处理字符和符号;他们处理比特和字节。
你在电脑屏幕上看到的每一段文本实际上都是以特定的字符编码存储的。
有许多不同的字符编码,有些针对特定的语言进行了优化,比如俄语、汉语或英语,还有一些可以用于多种语言。
非常粗略地说,字符编码提供了你在屏幕上看到的东西和你计算机实际存储在内存和磁盘上的东西之间的映射。

实际上,情况比这更复杂。
许多字符在多种编码中是通用的,但是每种编码可能使用不同的字节序列来实际将这些字符存储在内存或磁盘上。
所以你可以把字符编码想象成文本的一种解密密钥。
每当有人给你一个字节序列并声称它是“文本”时,你需要知道他们使用了什么字符编码,这样你就可以把字节解码成字符并显示出来(或者处理它们,或者其他什么)。


2、什么是字符编码自动检测?

这意味着以未知字符编码获取字节序列,并尝试确定编码,以便您可以阅读文本。
这就像在没有解密密钥时破解代码一样。


3、那不是不可能吗?

总的来说,是的。
然而,有些编码是针对特定语言优化的,语言不是随机的。
一些字符序列一直弹出,而其他序列毫无意义。
一个英语流利的人打开一份报纸,发现“txzqJv 2!dasd0a QqdKjvz”会立即识别出那不是英语(即使它完全由英语字母组成)。
通过研究大量“典型”文本,计算机算法可以模拟这种流畅性,并对文本的语言做出有根据的猜测。

换句话说,编码检测实际上是语言检测,结合了哪些语言倾向于使用哪些字符编码的知识。


4、这个检测算法是谁写的?

这个库是Mozilla中自动检测代码的一个端口。
我试图保留尽可能多的原始结构 可能(主要是出于自私的原因,为了更容易维护 端口随着原始代码的演变)。
我也保留了原来的 作者的评论,内容相当广泛和翔实。

你可能也对导致 Mozilla实现,一种语言/编码检测的复合方法


5、耶!去***标准,我会自动检测一切!

不要这样做。
几乎每种格式和协议都包含一种指定字符编码的方法。

  • HTTP可以定义一个charset参数在Content-type 标题。

  • HTML 文档可以定义一个<meta http-equiv="content-type"> 网页<head>中的元素。

  • XML文档可以在XML序言中定义encoding属性。


如果文本带有显式字符编码信息,您应该使用它。
如果文本没有显式信息,但相关标准定义了默认编码,您应该使用它。
(这比听起来难,因为标准可能重叠。
如果您通过HTTP获取XML文档,您需要支持这两种标准,并确定如果它们提供冲突的信息,哪一种会获胜。)

尽管很复杂,但遵循标准并尊重显式字符编码信息是值得的 几乎可以肯定比尝试自动检测更快更准确 编码。
它还将使世界变得更美好,因为您的 程序将与遵循相同规则的其他程序互操作 标准。


6、如果自动检测速度慢、不准确且不标准,为什么还要费心呢?

有时您会收到带有可验证的不准确编码信息的文本。
或者没有任何编码信息的文本,并且指定的默认编码不起作用。
还有一些设计不佳的标准根本无法指定编码。

如果遵循相关标准一事无成,你决定 处理文本比维护更重要 互操作性,然后可以尝试自动检测字符编码 作为最后的手段。
一个例子是我的通用提要解析器,它称之为自动检测 库只有在用尽所有其他选项之后


2024-09-24(二)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

AI工程仔

请我喝杯伯爵奶茶~!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值