Chardet:通用字符编码检测器

Python版本:需要Python 2.6,2.7或3.3+
文档地址:https://chardet.readthedocs.io/

检测字符集范围:

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

基本用法

  1. chardet.detect(byte_str)

byte_str参数必须是字节类型(bytes)字符串,否则就会报如下错误:

TypeError: Expected object of type bytes or bytearray, got:

python有两种不同的字符串,一种存储文本,一种存储字节。对于文本python内部采用unicode存储,而字节字符串显示原始字节序列或者ASCII
python3,文本字符串类型(使用unicode数据存储)被命名为str,字节字符串类型命名为bytes。
一般情况下,实例化一个字符串会得到一个str对象,如果想得到bytes,那就在文本之前加上前缀b,或者encode一下。所以,str对象有一个encode方法,bytes对象有一个decode方法

  1. import chardet
  2. s = '编码'.encode()
  3. print(chardet.detect(s))

获取网页编码的示例:

  1. import requests
  2. import chardet
  3. urls = ['https://www.jb51.net', 'https://www.baidu.com/']
  4. for url in urls:
  5. r = requests.get(url)
  6. print(url, chardet.detect(r.content))
  7. output
  8. https://www.jb51.net {'encoding': 'GB2312', 'confidence': 0.99, 'language': 'Chinese'}
  9. https://www.baidu.com/ {'encoding': 'utf-8', 'confidence': 0.99, 'language': ''}

获取文本编码的示例:

  1. import chardet
  2. with open('strcoding.py','rb') as f:
  3. print(chardet.detect(f.read()))
  4. # output:
  5. {'encoding': 'utf-8', 'confidence': 0.9690625, 'language': ''}

逐步检测编码

对于简短的网页或者文本内容,我们可以按照上述的方式进行操作,但如果我的文本是以G为单位计算的,如何能快速的获取文本的字符集内容呢?我们可以使用chardet模块的逐步检测编码方式,下面我们来对比下两者的差距,我这里就不用G级的数据了,那伏天氏小说的11MB内容就已经很能说明问题了:

  1. # 原始方法
  2. import chardet
  3. import time
  4. t0 = time.process_time()
  5. with open("伏天氏.txt",'rb') as f:
  6. print(chardet.detect(f.read()))
  7. t1 = time.process_time()
  8. print(t1-t0)
  9. # output:
  10. {'encoding': 'utf-8', 'confidence': 0.99, 'language': ''}
  11. 105.3786755
  1. # 逐步检索方法:
  2. import time
  3. from chardet.universaldetector import UniversalDetector
  4. detector = UniversalDetector()
  5. t0 = time.process_time()
  6. for line in open("伏天氏.txt", 'rb'):
  7. detector.feed(line)
  8. if detector.done:
  9. break
  10. detector.close()
  11. print(detector.result)
  12. t1 = time.process_time()
  13. print(t1 - t0)
  14. # output:
  15. {'encoding': 'utf-8', 'confidence': 0.99, 'language': ''}
  16. 45.1466894

我们可以看到,原始的方法,我们需要将所有的文本全部读取后,一行行的检测,最终获取结果,但使用UniversalDetector的方式,进行逐行判断,当系统读取进度觉得可以确定字符集编码时,就不再往下继续检测,从而返回结果。大大缩短了检测的时间