Unicode暗記してますか?
日本語で自然言語処理をやったことがある人なら誰もが一度はぶつかるであろう問題が、特定の文字種だけを抜き出す処理だと思います。
「python 正規表現 漢字」などで検索すると
re.search([あ-んア-ン一-鿐])
こんな感じの正規表現がよく見付かると思います。あ-ん
とア-ン
はまあいいとして一-鿐
これ本当に正しいんでしょうか?別のサイトでは[一-龠]
と書いてあったりして、よく分かりません。
そもそもこの形式の範囲指定でいいんでしょうか?つまりユニコードで本当に全ての漢字が一塊に配置されているんでしょうか?1
答えはノーで、この形式では漢字を取り零すか、漢字以外のものも含むかしかありません。(参考)
Unicode Script
そこでUnicode scriptの登場です。これはUnicode側の定義で文字種などを定義しているものになります。\p{Ascii}
や\p{Katakana}
などがあります。
なんかBlockとかPropertyとかSciptとか色々あって、厳密には違うみたいなんですが、調べてる+書いてる時間がないので、本記事ではScriptでいきます。
python以外の言語で漢字の正規表現方法を調べると、これを使った用例がいっぱい出てくると思います。
regexモジュール
ところがpythonの正規表現モジュールre
は、Unicode Scriptは使えません。
が、regex
という、re
の代替を狙ったモジュールがあり、こちらはUnicode Scriptに対応しています。
>>> import regex
>>> regex.findall(r'\p{Han}+',"朝早く起きた")
['朝早', '起']
このように、漢字だけにマッチしていることが分かります。
>>> print(regex.findall(r'[あ-んア-ン一-鿐]',"々"))
[]
>>> regex.findall(r'\p{Han}+',"々")
['々']
Unicode Scriptだけで拾える場合もあります。
漢字以外にもScriptによる文字種指定を使おう
気付いた人もいると思いますが、最初に出てきた[あ-ん]
は間違いです2。「ぁ」に引っ掛りません。片仮名も同様でかなり深刻ですよね。漢字だけでなく、平仮名、片仮名でも文字種で指定した方が安全ですね。
>>> regex.findall(r'\p{Katakana}+',"ファンターを飲んだ")
['ファンタ']
>>> regex.findall(r'\p{Hiragana}+',"ファンターを飲んだ")
['を', 'んだ']
ただし、延ばし棒が記号扱いで、拾えなかったりするので、そこは適宜補う必要があります3。
皆さんも是非、正規表現を使いこなして、楽しく日本語自然言語処理をしましょう。