読者です 読者をやめる 読者になる 読者になる

Λάδι Βιώσας

http://profile.hatena.ne.jp/kenkitii/

はてなダイアリーキーワードもどき

python

はてな日記キーワードの自動リンクって、どういうアルゴリズムでやってるんだろう?と思いググって見たところ、そのものずばりなページを見つけました。
はてなダイアリーキーワード自動リンクAPI
http://d.hatena.ne.jp/hatenadiary/20040205/1075960162
なんと正規表現でやってるそうな。これは簡単そう。。。と思ったので、ちょっと手元のcsvを使って実験してみました。

こんな感じの辞書ファイルと、

dict.csv
----------------
0001,はげ,hage
0002,ほげ,hoge
0003,ほが,huga

こんな感じのデータファイルがあるとします。

data.csv
----------------
hage.txt,1,hage,誰がなまはげだ
hoge.txt,2,hoga,彼はほがらかだがはげだ
hoge.txt,3,hoge,彼はほげいせんに乗ったはげだ
error.txt,4,error,僕はふさふさ

これらのファイルは手元にある適当なcsvファイルなので、必要ない情報も混ざってます。ここでやりたいことは、データファイルの「誰がなまはげだ」の列に、「はげ、ほげ、ほが」が含まれていたら強調表示する、という感じです。多分。


でコードを書いてみました。

keyword.py

import sys, re, csv
path_dict, path_data = sys.argv[1], sys.argv[2]

encoding = 'cp932'
col_keyword, col_data = 1, 3

reader = csv.reader(file(path_dict, "rb"))
keyword = [unicode(row[col_keyword], encoding) for row in reader]
pattern = re.compile(u"(" + u"|".join(keyword) + u")")

for row in csv.reader(file(path_data, "rb")):
    print pattern.sub(r"(\1)", unicode(row[col_data], encoding)).encode(encoding)

こんな感じで使えます。

kenkiti@X32M8J ~/wk$ python keyword.py dict.csv data.csv
誰がなま(はげ)だ
彼は(ほが)らかだが(はげ)だ
彼は(ほげ)いせんに乗った(はげ)だ
僕はふさふさ

最後の行で置換後の文字列"(\1)"を指定しているので、気に入らない場合は変更してください。
試しに1500語の辞書を使って2000行くらいのcsvファイルのキーワードを強調してみたところ、あっというまでしたですよ。正規表現なんだからそりゃそうだよな。。。

      • -

2006.09.09追記

      • -

上のエントリーに対して、id:odzさんより突っ込みがありました。
odz buffer - [Python][Regexp]メタキャラクタとORの扱い
http://d.hatena.ne.jp/odz/20060909/1157779591
詳細はodzさんのエントリーを見ていただくとして、、、重要な点を引用させていただきました。

  • キーワード文字列にメタキャラクタが含まれていた場合酷いことになるので、正規表現の生成は以下のようにエスケープすべき
pattern = re.compile(u"(" + u"|".join(re.escape(k) for k in keyword) + u")")
  • 単語数が1万越えたあたりで以下のエラーがでるよ
RuntimeError: internal error in regular expression engine

という2点です。ご指摘ありがとうございます。大変勉強になりました。