異体字同一視検索

Pocket

オンライン辞書の北辞郎には、利用者が検索した際、データベースにその語句が含まれていないと候補の単語を提示する機能を設けてある。
今回システムの更新を行い、異体字を同一視して候補を表示する機能を追加した。備忘録をかねて内部でどういう処理を行っているかまとめておく。

まず、異体字を同一視して検索する、という処理がどういうものか定義しておくと、「発展」と入力すると「発」の異体字である「發」や「发」を展開し、「發展」、「发展」に対する検索も同時に行うことを指す。正規表現で表すと「(発|發|发)展」を検索することになる。これを実現するには「発展」を与えると「(発|發|发)展」を返す関数がまず必要である。さまざまな方法があるが、今回はシンプルに単漢字をキーとし、対応する異体字のリストを値とする連想配列を用意した。以下にその一部を示す。なお、北辞郎はPHPで構築しているので以下のコードはすべてPHPである。

$variants = array(
    "皑" => "皑|皚",
    "皚" => "皚|凒|皑",
    "蔼" => "蔼|藹",
    "藹" => "藹|譪|蔼",
    "霭" => "霭|謁|靄",
    "靄" => "靄|謁|霭",
    "爱" => "爱|愛",
    "愛" => "愛|㤅|爱",
    "暧" => "暧|曖",
    "曖" => "曖|暧",
    "谙" => "谙|諳",
    "諳" => "諳|谙",
    "鏖" => "鏖|鏕|鏖",
    "鳌" => "鳌|鼇|鰲",
    "鰲" => "鰲|鼇|鳌",
    "媪" => "媪|媼",
    "媼" => "媼|媪",
    "拔" => "拔|抜",
    "抜" => "抜|杮|叐|㧞|拔",
    "罢" => "罢|罷",
    "罷" => "罷|羆|罴|罢",
    "摆" => "摆|襬|擺",#以下延々と1万文字以上続く
);

異体字のデータには、自前の簡体字と日本の漢字の対照データと漢字データベースの異体字データベースを利用した。異体字データベースは、異体字の情報が網羅された素晴らしいデータベースである。作成に携わった全作業者にこの場を借りてお礼申し上げる。

この配列ができてしまえば、処理は半分終わったようなものである。あとは文字列が与えられるとそれを文字単位に分解し、各文字に対応する異体字を検索して正規表現を返す関数を作れば良い。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
function get_variants($str) {
    #まず先ほどの配列が保存してあるファイルをインクルードする
    #配列の変数名は$variantsである
    include 'variants.php';
    $result = "";
    for ($i = 0; $i < mb_strlen($str); $i++) {
        #文字単位にばらす
        $char = mb_substr($str, $i, 1);
        if (array_key_exists($char, $variants)) {
            $result .= "(" . $variants[$char] . ")";
        } else {
            $result .= $char;
        }
    }
    return $result;
}

このget_variantsにたとえば「広東」を与えると「(広|廣|广)(東|东)」が返ってくる。この正規表現を使ってデータベースの検索を行えば、「広東」と「广东」と「廣東」の検索をまとめて行うことができる。北辞郎で採用しているデータベースSQLiteで正規表現を使用する方法については、こちらのSQLiteで正規表現にまとめたので参照されたい。実用上問題のない処理速度をマークしており、手間の割に満足のいく結果が得られた。

今回作成した variants.php は、以下からダウンロード可能である。興味のある向きは参照されたい。なお、このデータのライセンスは、異体字データベースと同じMITライセンスとする。

ダウンロード:variants.zip(文字コードはUTF-8)

コメントを残す

メールアドレスが公開されることはありません。