文字列の符号化方式を調べる

ファイル読み込みなど、外部から取得した文字列のencodingを得る方法を調べてたら、chardetとpykfが見つかったので試してみる。

chardet 2.1.1 : Python Package Index
pykf 0.4 : Python Package Index

# coding=utf-8
import chardet
import pykf


PYKF_ENCODE_MAP = {
    pykf.UNKNOWN: None, pykf.ASCII: 'ASCII',
    pykf.SJIS: 'SHIFT_JIS', pykf.EUC: 'EUC-JP',
    pykf.JIS: 'ISO-2022-JP', pykf.UTF8: 'UTF-8',
    pykf.UTF16: 'utf-16', pykf.UTF16_BE: 'utf-16_be',
    pykf.ERROR: None
}


def test(content):
    print "testing..", content

    for e in ['iso2022jp', 'sjis', 'eucjp', 'utf-8']:
        print u'encode to', e
        s = content.encode(e)
        encoding = chardet.detect(s)
        print 'chardet detect', encoding['encoding']
        print 'pykf detect', PYKF_ENCODE_MAP[pykf.guess(s)], "\n"

test(u"あいえうえおかきくけこ")
test(u"あ")


結果

testing.. あいえうえおかきくけこ
encode to  iso2022jp
chardet detect ISO-2022-JP
pykf detect ISO-2022-JP 

encode to sjis
chardet detect SHIFT_JIS
pykf detect SHIFT_JIS 

encode to eucjp
chardet detect EUC-JP
pykf detect EUC-JP 

encode to utf-8
chardet detect utf-8
pykf detect UTF-8 

testing.. あ
encode to iso2022jp
chardet detect ISO-2022-JP
pykf detect ISO-2022-JP 

encode to sjis
chardet detect windows-1252
pykf detect SHIFT_JIS 

encode to eucjp
chardet detect EUC-JP
pykf detect EUC-JP 

encode to utf-8
chardet detect utf-8
pykf detect UTF-8 

chardetは文字列が短いとミスるとどこかに書いてあったけど、確かにsjisを上手く判定できなかった。


外字を符号化可能なencodingを指定してやってみた

content = u"\u2460\u2461\u2462\u2463\u2464"


print "testing..", content

for e in ['utf8', 'shiftjis2004', 'iso2022jp-2004', 'eucjis2004']:
    print u'encode to', e
    s = content.encode(e)
    encoding = chardet.detect(s)
    print 'chardet detect', encoding['encoding']
    print 'pykf detect', PYKF_ENCODE_MAP[pykf.guess(s)], "\n"
testing.. ?????
encode to utf8
chardet detect utf-8
pykf detect UTF-8 

encode to shiftjis2004
chardet detect windows-1252
pykf detect SHIFT_JIS 

encode to iso2022jp-2004
chardet detect None
pykf detect ISO-2022-JP 

encode to eucjis2004
chardet detect IBM866
pykf detect EUC-JP 

こちらもchardetのほうがミスってる感じ