chardetというPythonのライブラリがある。bytes列を入力すると、bytes列が何の文字コードで書かれた文字列をエンコードしたものだったのかを推論することができる。
chardetをPython3で使おうと思ったが、公式はまだPython3に対応していない。
探してみたところ、python3-chardetという、chardetをforkしたライブラリを見つけたのでそれを使うことにした。
※追記 cChardetのほうが速いのでそっちのほうが使いやすい。記事の下に追記した。
インストール
githubからダウンロードしてインストールする。
$ git clone git@github.com:bsidhom/python3-chardet.git
で作ったディレクトリで
$ python setup.py install
するとインストール完了。
実験
import chardet
chardet.detect('abc'.encode('utf-8'))
> {'confidence': 1.0, 'encoding': 'ascii'}
chardet.detect('あいうえお'.encode('utf-8'))
> {'confidence': 0.9690625, 'encoding': 'utf-8'}
chardet.detect('あいうえお'.encode('Shift-JIS'))
> {'confidence': 0.5, 'encoding': 'windows-1252'}
ちゃんと動いた。'あいうえお'.encode('Shift-JIS')がwindows-1252だと判定されたのはちょっと不安だが、confidenceが0.5なのでchardet自信も半信半疑なのだろう。文が短すぎたので仕方がない。
Webページをスクリプティングするときに使えるか、さらに実験を行った。
対象となるWebサイトは価格.com http://kakaku.com/ に決定。Shift_JISを使っているのでちょうどよい。
import chardet
import requests
r = requests.get('http://kakaku.com')
chardet.detect(r.content)
> {'confidence': 0.99, 'encoding': 'SHIFT_JIS'}
うまく判別してくれた。'あいうえお'.encode('Shift-JIS')の例と異なり、windows-1252ではなくSHIFT_JISと正確に判断してくれたのは、Webページ全体を対象とした長いbytes列を対象にしたからと思われる。confidenceも高くなった。
追記
cChardetというC拡張のPythonライブラリがあることにあとで気づいた。Python3で使える。PyYoshiさんすごい。
pypiにあるので https://pypi.python.org/pypi/cchardet/ pipで取ってこれる。
$ pip install cchardet
せっかくなので、さきほどの価格.comのトップページを利用して、速度比較を行った。コードは以下の通り。
import chardet
import cchardet
import requests
import time
if __name__ == '__main__':
r = requests.get('http://kakaku.com')
begin_time = time.clock()
guessed_encoding = chardet.detect(r.content)
end_time = time.clock()
print('chardet: %f, %s' % (end_time - begin_time, guessed_encoding))
begin_time_of_cc = time.clock()
guessed_encoding_by_cc = cchardet.detect(r.content)
end_time_of_cc = time.clock()
print('cChardet: %f, %s' % (end_time_of_cc - begin_time_of_cc, guessed_encoding_by_cc))
そして結果は以下のようになった。
chardet: 1.440141, {'confidence': 0.99, 'encoding': 'SHIFT_JIS'}
cChardet: 0.000589, {'confidence': 0.9900000095367432, 'encoding': 'SHIFT_JIS'}
圧倒的ではないか。
結論
cChardetを使おう!!!