[Python] 使用 chardet 偵測字串的編碼
最近專案需要把一個檔名,從未知的編碼轉成 Unicode 處理…
為什麼會有未知的編碼呢?
因為檔案名稱可能是從中文 Windows 用 winscp 直接拖到 Linux 上去的 (那就會是 BIG5),
或是從郵件中解出來的檔名 (那有可能是 UTF-8 或是寄件者設定的郵件編碼),
或是從其他拉拉雜雜的不明來源取得的檔名…
這樣的檔名要處理起來很困難,
當拿到一個中文 BIG5 編碼的字串,卻用日文 SHIFT-JIS 來解譯的話,
最後要嘛是呈現上出現怪怪的字,要嘛還會出現其他的災難…
問題是,要怎麼用 python 知道任意字串的編碼呢?
事實上是沒有完美的解法,
Google 一下就可以看到一堆人在求問,然後也有一堆人在解釋,
因為同樣的 bytes 在 BIG5 裡是合法字元,在 SHIFT-JIS, GBK… 等等,
可能都是合法字元,所以根本分不出來…
不過雖然沒有完美的解法,網路上還是有不少套件幫忙「猜」字串的編碼,
還是可以試試看的~
chardet 是蠻多人建議使用的 python 套件,使用上也很簡單:
1. 使用 pip 安裝 chardet
如果 pip 還沒有安裝的話,參考一下 pip installation 這邊,
然後執行下面的指令,就可以裝好 chardet 套件了~
sudo pip install chardet
2. 執行 chardet
執行 chardet.detect() 函式就可以偵測字串「最有可能」的編碼~
>>> import chardet >>> chardet.detect("this is english") {'confidence': 1.0, 'encoding': 'ascii'} >>> chardet.detect('\xa4\xa4\xa4\xe5\xa4\xa4') {'confidence': 0.5, 'encoding': 'windows-1252'} >>> chardet.detect('\xa4\xa4\xa4\xe5\xa4\xa4\xa4\xe5') {'confidence': 0.99, 'encoding': 'Big5'}
基本上如果給的字串越長,猜出來的準確度就越高~
像上例中,我給了「中文中」三個字的時候猜成了 windows-1252,
給了「中文中文」四個字的時候,就正確的猜到了 BIG5 了~
chardet.detect() 還會提供信心指數作參考…
不過真的只是參考, 我就遇過日文字串偵測為 SHIFT-JIS 的信心指數只有 20%,
可是中文字串偵測為 windows-1252 (幾乎所有 0~255 都是合法的編碼,只有少數不是) 的信心指數卻有 50%…
還有一次是日文字串完全偵測不出編碼,encoding 的值變成 None 了…
不過,畢竟還是一個可以參考的工具,就看如何使用了~
PS: 有些套件是號稱比 chardet 速度快的 (沒試過),但似乎都有些限制,
像是 cchardet 需要使用 cython,
而 fastchardet 只支援 ASCII, UTF-8, windows-1252,算是少的可憐…