chardet使用方法


簡單用法

chardet的使用非常簡單,主模塊里面只有一個函數detect。detect有一個參數,要求是bytes類型。bytes類型可以通過讀取網頁內容、open函數的rb模式、帶b前綴的字符串、encode函數等途徑獲得。

示例代碼:

import chardet

some_string = '你好,世界。'.encode('utf-8') # encode方法返回一個bytes
# b'\xe4\xbd\xa0\xe5\xa5\xbd\xef\xbc\x8c\xe4\xb8\x96\xe7\x95\x8c\xe3\x80\x82'

result = chardet.detect(some_string) # 調用檢測接口

print(result)
# {'encoding': 'utf-8', 'confidence': 0.99}

如上所示,detect函數返回一個字典,字典里有兩個key-value對。其中一個的key值為encoding,代表chardet推斷出來的編碼格式。另一個key值為confidence,代表可信度。可信度是一個0到1之間float值,0代表不可信,1代表百分之百可信。


高級用法

當用於檢測的文檔特別大時,可以chardet的子模塊chardet.universaldetector。這個模塊允許我們分多次(逐行讀取或者自行斷行讀取)檢測文本的編碼格式,當達到一定的閾值時便可以提前退出檢測。這樣做可以有效地節省資源,提高程序效率,同時保證檢測結果的准確性。

示例代碼:

 

from chardet.universaldetector import UniversalDetector

detector = UniversalDetector() # 初始化一個UniversalDetector對象
f = open('test.txt', 'rb') # test.txt是一個utf-8編碼的文本文檔

for line in f:
    detector.feed(line) # 逐行載入UniversalDetector對象中進行識別
    if detector.done: # done為一個布爾值,默認為False,達到閾值時變為True
        break

detector.close() # 調用該函數做最后的數據整合
f.close()
print(detector.result)
# {'confidence': 1.0, 'encoding': 'UTF-8-SIG'}

需要注意的是:如果對多個不同來源的文本進行檢測,在每次檢測完畢時,必須調用一次UniversalDetector對象的reset函數,將之前的檢測數據清除。否則會導致后面的檢測結果混亂。


目前支持的編碼格式

Universal Encoding Detector目前支持以下編碼格式:

  • Big5, GB2312/GB18030, EUC-TW, HZ-GB-2312, and ISO-2022-CN (Traditional and Simplified - Chinese 繁體和簡體中文)
  • EUC-JP, SHIFT_JIS, and ISO-2022-JP (Japanese 日文)
  • EUC-KR and ISO-2022-KR (Korean 韓文)
  • KOI8-R, MacCyrillic, IBM855, IBM866, ISO-8859-5, and windows-1251 (Russian 俄文)
  • ISO-8859-2 and windows-1250 (Hungarian 匈牙利文)
  • ISO-8859-5 and windows-1251 (Bulgarian 保加利亞文)
  • ISO-8859-1 and windows-1252 (Western European languages 西歐文字)
  • ISO-8859-7 and windows-1253 (Greek 希臘文)
  • ISO-8859-8 and windows-1255 (Visual and Logical Hebrew 視覺順序和邏輯順序的希伯來文)
  • TIS-620 (Thai 泰文)
  • UTF-32 BE, LE, 3412-ordered, or 2143-ordered (with a BOM 帶字節序標記)
  • UTF-16 BE or LE (with a BOM 帶字節序標記)
  • UTF-8 (with or without a BOM 帶或者不帶字節序標記)
  • ASCII

注意:由於內部的相似性,某些情況下會出現檢測錯誤。最常出問題的是匈牙利文,會出現報告的編碼是兩種之中的另一種。希臘文的檢測也經常錯誤的將ISO-8859-7識別為匈牙利文的ISO-8859-2。


關於檢測時出現的奇怪錯誤

該模塊在檢測ANSI編碼(在中文版windows系統上就是gbk)的時候會出現一些奇怪的錯誤,博主正在研究英文文檔,希望能在上面找到答案。如果有后續,會同步更新至本文。

接上文:

問題來源:某些情況下檢測ANSI編碼的文本文檔和gb2312編碼的字節包會出現錯誤。

過程:博主分別對不同情況下錄入、不同長度和不同編碼的字節包進行了測試。並仔細看了一遍官方文檔。大概理出了個思路。

解析:官方文檔上有一段話,我先原文摘下來。

If UniversalDetector detects a high-bit character in the text, but none of the other multi-byte or single-byte encoding probers return a confident result, it creates a Latin1Prober (defined in latin1prober.py) to try to detect English text in a windows-1252 encoding. This detection is inherently unreliable, because English letters are encoded in the same way in many different encodings. The only way to distinguish windows-1252 is through commonly used symbols like smart quotes, curly apostrophes, copyright symbols, and the like. Latin1Prober automatically reduces its confidence rating to allow more accurate probers to win if at all possible.

大概意思是,當UniversalDetector在解析一些字節的時候,如果沒有相應的探測器給出報告,它就會調用一個叫做Latin1Prober的探測器試圖用英文編碼windows-1252來解析該字節包,這個探測器非常不可信(官方吐槽…)。通常情況下英文字母和一些特殊符號在不同的編碼里是一樣的,所以這個探測器會給出很高的可信度。這個探測器會自動地壓低自己給出的可信度以讓其他探測器可以優先通過。

再根據以下這段原文:

The main entry point for the detection algorithm is universaldetector.py, which has one class, UniversalDetector. (You might think the main entry point is the detect function in chardet/init.py, but that’s really just a convenience function that creates a UniversalDetector object, calls it, and returns its result.)

大致意思是:檢測算法的入口是UniversalDetector,chardet.detect函數僅僅只是方便用戶使用的語法糖。

可以得出類似的機制也會出現在detect函數中。盡管Latin1Prober已經做了優化,但是還是會有一些情況下它給出了遠超實際的可信度。比如下面這個實驗:

 

博主還做了幾個其他的實驗,得出了一個結論:當字節包的長度不夠長時,chardet給出的結論是很不可靠的,因為它可能在調用一個不相干的探測器時,該探測器給出了一個超過閾值的可信度,或者兩個編碼格式剛好有共通的字符,然后就不再往下檢測。這么做很容易出現不可靠的檢測結果。所以最好不要檢測很少量的字節。同時,在檢測開篇有大段其他字符的文檔時,最好先手動處理掉無關的符號(不一定會發生錯誤,因為程序根據初次遍歷結果對探測器的順序做了優先級排序,但是保不准會出錯),以求最准確的結果。

How Universal Encoding Detector Works這個網址詳細地說明了模塊是如何運作的。建議能看懂英文並且有耐心的讀者通讀一遍。博主只是選擇性地快速閱讀了一遍,不能保證把原作者的意思傳達到各位這里,但是也能保證偏差不會太大。

支持原創-->原文鏈接


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM