|
カテゴリ:Python
Python でエンコーディングの自動判定をするにはいくつかの方法がある。文字列のコードを直接調べてその情報だけで判定するタイプと、HTML や XML ファイルに含まれるメタ情報なども利用し、そうした情報で判定できないものは文字コードの情報から判定するタイプがある。
前者のタイプでは、pykf や、nkfpython、kanjilib などがある。pykf は、ShiftJIS, EUC-JP, JISコードを相互に変換するためのPython拡張モジュールで、Universal Encoding Detector や encutils のようには、メタ情報を使わない直接文字コードをチェックするタイプ。日本語のみを前提とするのであれば、比較的短い文字列であっても、正しい判定をしてくれる。一時、入手が難しかったが、sourceforge で再公開されたので、今は入手できる。Windows 環境用には Python 2.4 と 2.5 のバイナリも公開されている (pykf download)。 nkfバージョン2用 python インターフェース という、日本語漢字フィルタ nkf バージョン2用の python インターフェースを公開されていらっしゃる方もあるが、バイナリは Python 2.4 用のみで、2007年2月1日が最終公開日。自分でコンパイルするには、nkf2 のソースコードも用意する必要がある。 Pure Python のものでは kanjilib などが is_sjis や is_euc といった関数を持っているので、これもあり(ちょっと古いソースなので、そのままだと warning が出る。ソースに EUC-JP が含まれているので、今時の環境で使うなら # -*- encoding: euc-jp -*- を先頭に入れる)。 後者のものとしては、Mark Pilgrim さんの Universal Encoding Detector があるが、他にも、Christof Hoeke さんの encutils があるのでちょっと使ってみた。Universal Encoding Detector も、encutils も、直接短い文字列を渡して判定すると、判定をしくじる場合があるが、HTML ファイルや XML ファイルのようにエンコーディングの指定がちゃんと含まれているようなものであれば問題はない。けれど、どちらもデフォルトが windows-1252 に落ちるようで、短めの文字列のみを判定させると、そこが不幸の原因になる場合がある。 Universal Encoding DetectorUniversal Feed Parser の Universal Encoding Detector (Character Encoding Detection) を使う方法を見てみる。auto-detection code in Mozilla のアルゴリズムが使われていて、そこそこよい判定をしてくれる。 easy_install chardet でインストールして、
ただし、エンコーディングが指定されている HTML ファイルや XML ファイル等であれば、メタ情報を利用しているので正しく判定されるので問題ないが、文字コード判定ライブラリ Universal Encoding Detector にあるように、短い個別の文字列を渡してやると判定をしくじる場合がある。
メタ情報がないときには文字の出現頻度を使っているからのようだ。
ということで、そういう場合には pykf の方が安全と。 encutils - encoding detection collection for Pythonencutils は、新しくエンコーディングの判定のために作られたライブラリで、HTML, XHTML, XML, CSS 等のテキストファイルのエンコーディングの判定ができる。Universal Encoding Detector を使うときには urllib を別途インポートしなければいけないのに対して、encutils は、内部で urllib をインポートしているので、少しだけ、コードの量が少なくて済む。また、media type の情報も取り出して利用できるようにしているところが特徴か。BOM 付きのファイルに対してもちゃんと見ているので安心。ただし、chardet と違って、判定の確信度はない。 easy_install encutils でインストールして試す。
Universal Encoding Detector にやったのと同じように意地悪してみる。
やはり、判定に失敗する。同じようなロジックなのだろうかと見てみると、encutils は tryEncodings の中で文字列を直接判定するときに、Universal Encoding Detector (chardet) がインストールされていると、それを使って判定していた。インストールされていなければ、独自のやり方で判定する。
独自の判定方法は、'ascii','iso-8859-1', 'windows-1252', 'utf-8' の順に、 text.encode(e) を try して、例外が発生したら次のエンコーディングを試し、変換できたら、それに決まりという流れ。従って、SHIFT_JIS や EUC-JP、ISO-2022-JP などに落ちることはない。ここに、'shift_jis', 'euc_jp', 'iso-2022-jp' を追加してやれば、chardet がなくても日本語が判定できるようになるだろう。けど、ちょっと強引だから精度は落ちるだろう。 なので、ここに pykf を使った判定を入れるようにすれば、高い精度の文字列判定ができるようになるはず。つまり、外側の情報を使って判定できるものはそうして、文字列を見なきゃ判定できないものは、pykf を使うという流れになる。 pykf + encutilspykf は、ShiftJIS, EUC-JP, JISコードを相互に変換するためのPython拡張モジュールで、日本人の atsuo ishimoto さんが公開しているもの。エンコーディングの判定機能も持っている。オリジナルは kf -- 漢字コード変換ソフト で、これを Python 対応にしたものだが、pykf は UTF-8 の判定もできる。
とすれば、Windows の SJIS の環境からだと SHIFT-JIS が返る。なので、とりあえずちょっと試しに 上記コードを encutils の __init__.py の中に適当に入れて(475行目から)、
とかしてみる。これで、短い文字列を判定させても、判定を間違えることはなくなった。けど、これはこれで ISO-8859-1 の文字列を SJIS に判定したりとかなっちゃうので困るときもある。文字列が長くても、短くても、日本語でも西欧の文字でも、もう少し判断がこけない方法はないかなぁ。chardet のモデルを少し調整して、もう少し日本語に倒れるようにできればよいのだけど。あちらをたてれば、こちらがたたずの部分はあるだろうけど。。。。 お気に入りの記事を「いいね!」で応援しよう
[Python] カテゴリの最新記事
|