« 400,005丁目 | メイン | 位置連動型広告始まる »

MeCabで住所抽出

「MeCab 0.90 だけをつかって Auto Link」を参考に、MeCabを使って住所抽出してみます。

元データとして国土交通省国土計画局国土情報整備室の街区レベル位置参照情報を利用します。ダウンロードページから、今回は平成18年度版の大阪府全域のデータ(27000-05.1a.zip)をダウンロードしました。

$unzip 27000-05.1a.zip
Archive:  27000-05.1a.zip
  Length     Date   Time    Name
 --------    ----   ----    ----
    14907  04-10-07 16:07   md_27_2006.xml
 24563015  06-11-07 21:01   27_2006.csv
     3325  01-22-07 20:00   format_2006.html
 --------                   -------
 24581247                   3 files
$head -3 27_2006.csv | nkf -e
"都道府県名","市区町村名","大字・町丁目","街区符号・地番","座標系番号","X座標","Y座標","緯度","経度","住居表示フラグ","代表フラグ","平成17年度履歴フラグ","平成18年度履歴フラグ"
"大阪府","茨木市","鮎川一丁目","1",6,-131247.8,-37365.6,34.816231,135.591556,1,1,0,0
"大阪府","茨木市","鮎川一丁目","2",6,-131248.3,-37346.4,34.816227,135.591766,1,1,0,0

MeCab の辞書を作るために dic.csv, matrix.def, char.def, unk.def の4つのファイルを作ります。

dic.csv: 辞書ファイルです。27_2006.csv を基に以下のようなファイルを作ります。

大阪府茨木市鮎川一丁目1,0,0,-16627,大阪府茨木市鮎川一丁目1,34.816231,135.591556
大阪府茨木市鮎川一丁目2,0,0,-16627,大阪府茨木市鮎川一丁目2,34.816227,135.591766
大阪府茨木市鮎川一丁目3,0,0,-16627,大阪府茨木市鮎川一丁目3,34.816491,135.592014

変換用のスクリプト(make_dic_csv.pl)は以下の通りです。

#!/usr/bin/perl

use strict;
use warnings;
use utf8;
use open ':encoding(shiftjis)';
binmode STDIN, ':encoding(shiftjis)';
binmode STDOUT, ":utf8";

while (<>) {
    next if (/^\"都道府県名/);
    my(@elm) = split(',', $_);
    my $address = $elm[0] . $elm[1] . $elm[2] . $elm[3];
    $address =~ s/\"//g;
    my $cost = int(-400 * (length($address)**1.5));
    $cost = -36000 if ($cost < -36000);
    print "$address,0,0,$cost,$address," . $elm[7] . "," .  $elm[8] . "\n";
}

matrix.def: 連接表です。元記事と同様にします。

1 1
0 0 0

char.def: 文字セットの定義ファイルです。これも元記事と同じ。

DEFAULT 1 0 0
SPACE     0 1 0
0x0020 SPACE

unk.def: 未知語に対する品詞リスト。これも元記事と同じ。

DEFAULT,0,0,0,*
SPACE,0,0,0,*

dicrc: address というフォーマットを作成し、それがデフォルトの出力になるようにします。住所文字列の部分(と緯度経度)だけを出力するようにしています。

dictionary-charset = utf-8
cost-factor = 800
bos-feature = BOS/EOS
output-format-type=address
node-format-address = %H\n
unk-format-address =
eos-format-address  =

実行します。

$ls
char.def  dicrc  make_dic_csv.pl  matrix.def  src/  unk.def
$ls src
27_2006.csv
$ ./make_dic_csv.pl src/27_2006.csv > dic.csv
$/usr/lib/mecab/mecab-dict-index -f utf-8 -c utf-8
reading ./unk.def ... 2
emitting double-array: 100% |###########################################|
reading ./dic.csv ... 279452
emitting double-array: 100% |###########################################|
reading ./matrix.def ... 1x1

done!
$echo 昨日、大阪府大阪市中央区本町二丁目5に行った | nkf -w | mecab -d . | nkf  -e
大阪府大阪市中央区本町二丁目5,34.683834,135.504052

ここまでは結構簡単です。ただし、実用するには

  • 丁目、番地等の表記の正規化
  • 市レベル、区レベルから始まるエントリの追加
などの工夫が必要になります。

トラックバック

このエントリーのトラックバックURL:
http://www.mailpia.jp/cgi-bin/mt_32/mt-tb.cgi/90

コメントを投稿