chardet:字符编码探测器,自动检测文本、网页、xml的编码

楔子

在请求数据的时候,我们得到的可能是一堆字节,这个时候我们会通过decode将其解码。但是解码的前提是我们需要知道其对应编码是什么,比如:utf-8iso-8859-1gbk等等。而python也提供了相应的模块,用于检测字节对应的编码。

chardet检测编码

from chardet import detect

# 直接传入字节即可
print(detect(b"are you ok?"))  # {'encoding': 'ascii', 'confidence': 1.0, 'language': ''}
"""
可以看到返回一个字典,包含三个key:
encoding: 使用的编码
confidence: 检测的准确度
language: 所使用的语言
"""

对于其它语言也是支持的

from chardet import detect

chinese_utf8 = "你为什么这么熟练啊".encode("utf-8")
chinese_gbk = "你为什么这么熟练啊".encode("gbk")
print(detect(chinese_utf8))  
# {'encoding': 'utf-8', 'confidence': 0.99, 'language': ''}

print(detect(chinese_gbk))  
# {'encoding': 'GB2312', 'confidence': 0.8888888888888888, 'language': 'Chinese'}

我们看到当使用utf-8编码的时候,虽然能检测出编码,但是无法推测出语言,因为任何语言的字符都可以正常使用utf-8进行编码。但是下面的gbk是可以推断出语言的,因为这是专门用于中文的编码,显示的gb2312是gbk的子集。

from chardet import detect

jp_utf8 = "なんでそんなに慣れてんだよ".encode("utf-8")
jp_euc = "なんでそんなに慣れてんだよ".encode("euc-jp")
print(detect(jp_utf8))
# {'encoding': 'utf-8', 'confidence': 0.99, 'language': ''}

print(detect(jp_euc))
# {'encoding': 'EUC-JP', 'confidence': 1.0, 'language': 'Japanese'}

对于日文也是一样的,chardet支持多种语言。

尤其是向其它地方请求数据的时候,给你返回了一堆你不知道是什么编码的字节,这个时候就可以使用chardet,最典型的就是requests。

我们在使用requests的get方法之后,会调用text得到请求的html。但是有时候调用text返回的内容里面包含乱码,这是因为requests在内部是先获取的字节,然后再进行解码、返回,而在解码的时候,使用了错误的编码造成的

而一般我们在调用text之前,我们会手动指定使用的编码

import requests

res = requests.get("http://www.baidu.com")
# res.content: 会拿到html对应的字节流
# res.encoding: 所使用的编码,根据网站决定
# res.text: 会先获取res.content,然后通过res.encoding进行解码得到res.txt

# 但是默认的res.encoding不一定能够正常解码,这个时候我们会手动指定res.encoding
# 将res.apparent_encoding赋值给res.encoding
res.encoding = res.apparent_encoding
# 然后调用res.text就能正常打印内容了
print(res.text)

那么我们就可以进入源码中看看这个res.apparent_encoding是什么

    @property
    def apparent_encoding(self):
        """The apparent encoding, provided by the chardet library."""
        return chardet.detect(self.content)['encoding']

看到了吗?requests也是通过chardet检测对应的编码的,因为requests默认使用网站返回的编码,但是不一定靠谱。而通过这一步,会根据返回的字节手动推断出其使用的编码,然后赋值给res.encoding,这样再解码就没有问题了。

因此想知道返回的字节是什么编码的话,使用chardet是个很不错的选择。

原文地址:https://www.cnblogs.com/traditional/p/11877591.html