使用背景
Python 提供了 str 和 bytes 两种数据类型,但它们之间的编码格式一直让人头疼。我们知道文本的传输会经历编码、传输、解码的过程。在这个过程中,传递和接收方应该约定字符的编码格式,利用 encode() 和 decode() 来进行编码和解码的操作。这个过程如下:
编码:str.encode('编码类型')
解码:bytes.decode('编码类型')
如果不知道商品第一步的编码类型,我们就无法进行第二步的操作, 这时候我们就只能靠猜了。猜测的方法就是先收集部分的字符特征,然后根据这些特征进行一定的猜测,猜测过程大概率能够得到正确的编码类型。但是这个猜测过程是十分繁琐,费时又费力,这时候这个三方库 chardet 正好来解决这方面的问题, 用它来检测编码,即简单又易用。
安装
首先在终端进行安装:
pip install chardet
快速使用
给定一个字节串 bytes 进行检测:
import chardet
# 编码是 ascii 概率是1.0(即100%)
chardet.detect(b'gairuo.com')
'encoding': 'ascii', 'confidence': 1.0, 'language': ''} {
对中文编码后再进行编码测试:
data = '我是中国人'.encode('gbk')
# GB2312 是 gbk 超集,概率 74%, 语言为中文
chardet.detect(data)
# {'encoding': 'GB2312', 'confidence': 0.7407407, 'language': 'Chinese'}
data = '我是中国人'.encode('utf-8')
# 正确检测到
chardet.detect(data)
# {'encoding': 'utf-8', 'confidence': 0.99, 'language': ''}
一个典型的场景,我们爬取到一份数据,但不知道编码,可以用它进行检测:
import requests # 需要安装
rawdata = requests.get('http://yahoo.co.jp/').content
import chardet
chardet.detect(rawdata)
# {'encoding': 'utf-8', 'confidence': 0.99, 'language': ''}
打开文件时不知道编码,进行检测:
with open('202110-test-01.ipynb', 'rb') as f:
code = chardet.detect(f.read())
print(code)
# {'encoding': 'utf-8', 'confidence': 0.99, 'language': ''}
检测给定字节字符串的所有可能的编码:
data = '66顺'.encode('utf-8')
chardet.detect_all(data)
'''
[{'encoding': 'ISO-8859-1', 'confidence': 0.73, 'language': ''},
{'encoding': 'utf-8', 'confidence': 0.505, 'language': ''}]
'''
要使用结果就取返回字典的 encoding 值。
其他案例
增量检测编码
如果要检测多个文本(例如单独文件)的编码,可以重复使用单个 UniversalDetector 对象。只需在每个文件的开头调用 detector.reset() ,多次调用 detector.feed,然后调用detector.close() 并检查detector.result 字典中的文件结果。
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}
检测多个文件的编码
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)
支持的编码
通用编码检测器目前支持二十多种字符编码。
Big5, GB2312/GB18030, EUC-TW, HZ-GB-2312, 和 ISO-2022-CN (Traditional 和 Simplified Chinese)
EUC-JP, SHIFT_JIS, 和 ISO-2022-JP (Japanese)
EUC-KR 和 ISO-2022-KR (Korean)
KOI8-R, MacCyrillic, IBM855, IBM866, ISO-8859-5, 和 windows-1251 (Russian)
ISO-8859-2 和 windows-1250 (Hungarian)
ISO-8859-5 和 windows-1251 (Bulgarian)
ISO-8859-1 和 windows-1252 (Western European languages)
ISO-8859-7 和 windows-1253 (Greek)
ISO-8859-8 和 windows-1255 (Visual 和 Logical Hebrew)
TIS-620 (Thai)
UTF-32 BE, LE, 3412-ordered, 或者 2143-ordered (with a BOM)
UTF-16 BE 或者 LE (with a BOM)
UTF-8 (with or without a BOM)
ASCII
可检测中文、日文、韩文等多种语言。
其他
在读取数据过程中,遇到 csv 等文件中文如果不是 utf-8 编码,可试用 gbk,或者更多的字符集 GB2312、Big5、GB18030
参考
https://chardet.readthedocs.io/en/latest/index.html