ホリデープログラミング入門

ホリデーにプログラミングを楽しむための入門 by 船木信宏

全体表示

[ リスト ]

http://farm1.static.flickr.com/48/161243417_5d708b0fe5.jpg

exir.jp のPDFデータから人名を抽出する


抽出という単語は日常、あまり使いませんがここではたくさんあるデータの中から特定のデータを抜き出す、という意味で使っています。

大量のデータ(人間が一生かかっても読みきれないぐらい、あるいはそもそも目で見てもわからないようなデータ)から特定のデータを抽出するのは、ルールさえ決まっていればコンピュータの得意とするところです。

今回は上場企業のプレスリリースを集めているexir.jpのデータから人名を抽出してみることにします。

MeCabを使って形態素解析する


exir.jpのデータはオトモダチ特権でSQLで取得させてもらえました。
全データではありませんでしたが、それでもテキストで700MB程度。

で、ここから人名を抽出するわけですがそれにはまずMeCabを使います。MeCabがやってくれる形態素解析という処理は「私の名前は船木です」という文章から
私 名詞,代名詞,一般,*,*,*,私,ワタシ,ワタシ
の 助詞,連体化,*,*,*,*,の,ノ,ノ
名前 名詞,一般,*,*,*,*,名前,ナマエ,ナマエ
は 助詞,係助詞,*,*,*,*,は,ハ,ワ
船木 名詞,固有名詞,人名,姓,*,*,船木,フナキ,フナキ
です 助動詞,*,*,*,特殊・デス,基本形,です,デス,デス
と品詞ごとに分解してくれます。精度は100%ではないのと、元のテキストデータも若干おかしなところがあるのですが、今回は抽出してみるだけなので問題ないでしょう。

MeCabをコマンドラインから使える状態にしたら、
% nohup mecab /tmp/exir.txt -o /tmp/exir.analyzed -b 819200 >/tmp/results.log &
といった感じに実行します。exir.txtが元データ。MeCabは十分高速なのでさほど時間はかかりません。結果を保存したexir.analyzedは8GBを超えました。

分割する


このままだとファイルサイズが大き過ぎてPHPのfopenで開けず困るので(32bitなOSのとき:こちら参照)ファイルを分割します。
% split -C 1000m exir3.analyzed exir3.analyzed.split.
1GBずつのファイルが9つできました。これには結構時間がかかりました。

姓名だけ列挙


品詞があれこれありますが「名詞,固有名詞,人名」を取得するようにしました。
<?php
// exir_mecab.php
$fp = fopen($argv[1], 'r');
if (!$fp) {
die("cannot open file.\n");
}
$key = '名詞,固有名詞,人名,';
$keyLen = mb_strlen($key);
$lastName = null;
while (1) {
$buf = fgets($fp);
if ($buf == '') {
break;
}
if (($idx = mb_strpos($buf, $key)) !== false) {
$type = mb_substr($buf, $idx+$keyLen, 1);
if ($type === '姓') {
if (!empty($lastName)) { // 直前が人名のときはダメ
continue;
}
$lastName = mb_substr($buf, 0, $idx-1);
} else if ($type === '名' && !empty($lastName)) {
echo $lastName, " ", mb_substr($buf, 0, $idx-1), "\n";
$lastName = null;
}
} else {
$lastName = null;
}
}
fclose($fp);

これで姓名が列挙されたファイルが生成できます。
% php exir_mecab.php exir.analyzed >names.txt

数を数えてみる


<?php
$fp = fopen($argv[1], 'r');
$data = array();
while (1) {
$buf = fgets($fp);
if ($buf == '') {
break;
}
$name = trim($buf);
if (!isset($data[$name])) {
$data[$name] = 1;
} else {
$data[$name]++;
}
}
fclose($fp);
arsort($data);
foreach ($data as $name => $num) {
echo "$num\t$name\n";
}

こんな感じ。

結果


出力結果を見ると上位5位が
7899 銭 円
585 藤田 晋
564 オーク ション
410 高品 質
393 京 進
になっていました。。うーん。585回登場した藤田晋氏はサイバーエージェントの社長ですね。他はどうも形態素解析が間違ってしまったようです。

続く下位を見ていくと
322 植田 修平
314 井上 高志
283 銭 通
276 折口 雅博
227 伊藤 忠
218 南部 靖之
200 加藤 博敏
189 杉野 文則
188 大谷 省三
169 渡辺 博文
ところどころ人名でないものも含まれていますが、おおむね社長の名前が列挙されているようです。

一応何かに使えそうなデータになった?のでexirさんにお渡ししてみることにします。

閉じる コメント(0)

コメント投稿

顔アイコン

顔アイコン・表示画像の選択

名前パスワードブログ
絵文字
×
  • オリジナル
  • SoftBank1
  • SoftBank2
  • SoftBank3
  • SoftBank4
  • docomo1
  • docomo2
  • au1
  • au2
  • au3
  • au4
投稿

.


プライバシー -  利用規約 -  メディアステートメント -  ガイドライン -  順守事項 -  ご意見・ご要望 -  ヘルプ・お問い合わせ

Copyright (C) 2019 Yahoo Japan Corporation. All Rights Reserved.

みんなの更新記事