2010年9月16日木曜日

Pythonで unicodedata.normalize を使って全角半角を正規化する方法

(この記事は 2008年03月14日に別のブログに投稿した記事を移動・編集したものです。)

インターネット上の日本語を扱っていると、全角半角が統一されていない事による表記揺れをなんとかしたい場面に出くわします。半角で書かれた iPod も、全角で書かれたiPodも同じものとして扱いたいときや、あるいは単に見た目がきれいになるように、英数字は半角に、カタカナは全角にそろえたい、という場合です。

Python では setomitsさんによる zenhan.py を使うと、文字種ごとに全角半角を選択して変換することができ、除外文字も設定できるので便利です。ただ、そこまで柔軟でなくても良く、単に表記揺れがなくなれば良い、という場合も多いかと思います。その場合はPythonの標準ライブラリに含まれる unicodedata モジュールの normalize 関数を使うと便利です。

>>> import unicodedata
>>>
>>> s = 'フガホゲ-%*@ABC−%*@123'.decode('euc-jp')
>>> n = unicodedata.normalize('NFKC', s)
>>>
>>> print s.encode('euc-jp')
フガホゲ-%*@ABC−%*@123
>>>
>>> print n.encode('euc-jp')
フガホゲ-%*@ABC−%*@123

Unicode で定義される各文字は、等価な別表現がある場合(たとえば半角のAと全角のA)に、どの表現を標準とするべきか、という情報が付与されているそうです。normalize関数はこの情報を使って、表記を統一する処理を行います。normalize関数の第一引数に 'NFKC' を渡すことで、ガ(カ+濁点)のような複合文字が期待通りに分解・再合成されます。(詳しく知りたい方は Unicode正規化 あたりをどうぞ)

実際の変換結果を見てみると、英字、数字は半角に、カタカナは全角に正規化されることになっているようです。記号については、基本的に半角のようですが、全角マイナスと半角マイナスのように、別の文字として扱われているものもあるようです。マイナスが半角に正規化されるべきかどうかは場合によって異なると思われますが、ほとんどの用途にはこれで十分なのではないでしょうか。