楔子
在請求數據的時候,我們得到的可能是一堆字節,這個時候我們會通過decode將其解碼。但是解碼的前提是我們需要知道其對應編碼是什么,比如:utf-8、iso-8859-1、gbk等等。而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是個很不錯的選擇。
