文字コードの判定

python文字コードを判定するには普通kconvとかpykfとかchardetを使う。

何かの本(たしか「みんなのPython」だったと思う)を以前立ち読みをしてたら文字コードを判定するのに、適当なエンコーディングUnicodeに変換してみてUnicodeErrorが発生しないかどうか確かめるという恐ろしい方法が紹介されていた。具体的にはこんなコードになるか(うろ覚え)。

encodings = ('shift_jis', 'euc-jp', 'utf-8', 'iso2022_jp')

def chardetect(data):
    for enc in encodings:
        try:
            unicode(data, enc)
        except UnicodeError:
            continue
        return enc
    return None

数日前にこのコードを使ってみることがあったのだがそう悪くない。なんか頼りないが一応ちゃんと動く。

で、しばらく使っていると、判定に失敗するデータがあった。ちょっと調べてみると原因は機種依存文字。例えば機種依存文字が含まれるShift_JIS文字列もどきを変換しようとするとこうなる。

>>> data = '\x93\xfa\x96{\x8c\xea\x87@\x87A\x87B' #丸数字が入ってます
>>> unicode(data, 'shift_jis')
Traceback (most recent call last):
  File "", line 1, in 
UnicodeDecodeError: 'shift_jis' codec can't decode bytes in position 6-7: illegal multibyte sequence

これはどうしたものかと頭を捻っているとcp932という言葉が浮かんだ。

>>> unicode(data, 'cp932')
u'\u65e5\u672c\u8a9e\u2460\u2461\u2462'

ちゃんと変換できるなじゃないか。しかもUnicodeには丸付き文字があるのか?wikipediaにちょうどunicode表があったので2460を探してみる。
Unicode一覧 2000-2FFF - Wikipedia
あるじゃないか。unicodeってやつは超クールだな。念のため本家に行って確認してみると"CIRCLED DIGIT ONE"とか付いていた。(Code Chartsへ行って、ページトップのフォームに2460と入力すれば近くまで案内してくれる。)