Wikipedia見出しリストから不要な見出しをカットする
検索サイトで「wikipedia mecab」と検索するとWikipediaの見出しリストを整形してMeCab用辞書として使う記事が何件かhitします。
しかし、Wikipediaの見出しは形態素解析用に作られたわけではないので、形態素として扱うと不都合になることがあります。
たとえば、文書から名詞だけを抽出して文書をカテゴリに分類したいといったときに、「ロシアの音楽」という文字列を「ロシアの音楽/名詞」と解釈するよりも「ロシア/名詞 の/助詞 音楽/名詞」と解釈したほうが汎化できるので嬉しいです。
そのため不要な見出しを除去する処理を行うことにします。
まず、見出しリストをざっと見て「<国名>の法律」「<歌手>のディスコグラフィ」などの「AのB」パターンが多いことに着目しました。
そこで、AのBパターンをざっくりと抽出します。
#! /usr/bin/env python # -*- coding: utf-8 -*- from collections import Counter import re suffixes = Counter() re_anob = re.compile(u'(?P<A>.+[^の])の(?P<B>[^の].+)') re_hiragana = re.compile(u'[ぁ-ゖ]+') def extract_anob(text): match = re_anob.match(text) if match and is_valid_b(match.group('B')): suffixes[match.group('B')] += 1 def is_valid_entry(entry): return False if '_(' in entry else True def is_valid_b(b): return False if re_hiragana.match(b) else True if __name__ == '__main__': import optparse parser = optparse.OptionParser() parser.add_option("-f", "--filename", help="the path of input file") (opts, args) = parser.parse_args() for line in open(opts.filename, 'r'): line = line.strip().decode('utf8') if is_valid_entry(line): extract_anob(line) for k,v in suffixes.most_common(200): print k,v
AのBパターンのBの出現回数上位200件がこちら。
一覧 2256 戦い 1581 人物一覧 596 登場人物 467 歴史 452 法則 322 国旗 280 国歌 261 定理 256 国章 238 スポーツ 221 作品 199 通貨 198 地方行政区画 157 鉄道 156 音楽 153 大統領 150 世界遺産 149 軍事 146 冒険 145 廃校一覧 145 オールナイトニッポン 143 選手一覧 140 行政区画 131 航空 128 物語 125 映画 120 政治 120 同位体 117 野球 116 首相 116 政党 114 メジャーリーグベースボール 113 ワールドシリーズ 112 楽曲一覧 111 国会 110 海戦 101 宝塚歌劇公演一覧 99 ディスコグラフィ 93 日本公開映画 90 年度別成績一覧 90 世界 88 手紙 86 MLBオールスターゲーム 81 関係 80 経済 79 交通 79 逆襲 78 大冒険 77 政党一覧 77 ゲームタイトル一覧 77 年表 77 連続ドラマ 76 伝説 75 時間 75 バレーボール 73 原理 73 エピソード一覧 72 歴代選手・スタッフ一覧 71 式内社一覧 69 反乱 69 アニメ 68 奇跡 66 F1世界選手権 65 ロードレース世界選手権 65 日本シリーズ 64 ユニフォーム 64 パラドックス 61 NBA 61 教育 61 登場人物一覧 61 権利 60 恋人 59 秘密 58 合戦 56 事件簿 56 女性史 54 郡一覧 52 虐殺 52 料理 52 高等学校一覧 52 ユーロビジョン・ソング・コンテスト 52 資格者配置路線 52 アメリカ合衆国上院議員 51 国鉄 50 有名人一覧 50 廃止市町村一覧 50 MLBドラフト 49 空軍 49 悲劇 48 廃園一覧 48 NFL 48 原則 47 登場キャラクター 47 ナショナルリーグチャンピオンシップシリーズ 46 肖像 46 市町村章一覧 46 野望 46 地理 45 文化 45 アメリカンリーグチャンピオンシップシリーズ 45 県道一覧 45 騎士 44 日々 43 文学 42 テーマ 41 世界ラリー選手権 41 誓い 41 公式 41 大学一覧 41 ニュース 40 灯台一覧 40 海軍 39 二級水系一覧 39 比較 39 日本競馬 38 方程式 37 国・地域別メダル受賞数一覧 37 王様 37 少女 37 時代 37 博物館 36 季節 36 オールナイトニッポンR 36 野鳥一覧 36 町名 36 中で 35 陸軍 35 自由 35 天使 34 観光地 34 カメラ製品一覧 34 人々 34 女王 33 議会 33 森公園 33 殺人 33 和約 33 科学 32 自転車競技 32 チーム記録 32 警察 31 陰謀 31 大統領一覧 31 部屋 31 歴代監督一覧 31 祈り 31 下で 30 促進に関する法律 30 問題 30 花嫁 30 政変 30 日本 30 NBAドラフト 30 サッカー選手一覧 30 約束 29 迷宮 29 記憶 29 リスト 28 韓国シリーズ 28 競馬 28 呪い 28 宇宙飛行 28 元素 28 相撲 28 ラジオ 27 事件 27 JSL 27 図書館一覧 27 聖母 27 スーパーバイク世界選手権 26 ワイン 26 渡し 26 作品一覧 26 神話 26 日記 26 青春 26 理論 26 用語一覧 26 宗教 25 女神 25 挑戦 25 憲法 25 ユーロ硬貨 25 電車 25 秘宝 24 殿堂 24 戦争 24 企業一覧 24 通り 23 兵器 23 結婚 23 Jリーグ 23 全日本F3選手権 23 王国 23 サッカー 23 復讐 23 誕生 22 紋章 22 アリス 22
右の数字は出現回数です。
このうち一語の固有名詞として扱ったほうがいいもの(たとえば、**の冒険とか**の紋章とか)を人手で判断しました。
判断の補助としてmarisa-trieを使ってsuffixの検索を行うスクリプトを使いました。
#! /usr/bin/env python # -*- coding: utf-8 -*- import marisa_trie import os def is_valid_entry(entry): if '_(' in entry: return False return True def build_trie(filename): reversed_entries = [] for line in open(filename, 'r'): line = line.strip().decode('utf8') if is_valid_entry(line): reversed_entries.append(line[::-1]) trie = marisa_trie.Trie(reversed_entries) trie.save('wikipedia_reverse.marisa') if __name__ == '__main__': import optparse parser = optparse.OptionParser() parser.add_option("-f", "--filename", help="the path of input file") (opts, args) = parser.parse_args() if not os.path.exists('wikipedia_reverse.marisa'): build_trie(opts.filename) trie = marisa_trie.Trie() trie.load('wikipedia_reverse.marisa') while True: text = raw_input('>').decode('utf8') for i in trie.keys(text[::-1]): print i[::-1]
こうした作業によってできたリストがこちらです。見出しリストをMeCab用辞書に整形するときにこれを読み込んでlist型にして'文字列'.endswith(wikipedia_stop_suffixes)とかやって不要な見出しを弾くといいと思います。
一覧 の登場人物 の歴史 の国旗 の国歌 の国章 のスポーツ の作品 の通貨 の鉄道 の音楽 の大統領 の世界遺産 の軍事 のオールナイトニッポン の航空 の映画 の政治 の同位体 の野球 の首相 の政党 のメジャーリーグベースボール のワールドシリーズ の国会 のディスコグラフィ の日本公開映画 のMLBオールスターゲーム の関係 の経済 の交通 の年表 の連続ドラマ のバレーボール のアニメ の奇跡 のF1世界選手権 のロードレース世界選手権 の日本シリーズ のユニフォーム のパラドックス のNBA の教育 の女性史 の料理 のユーロビジョン・ソング・コンテスト の資格者配置路線 のアメリカ合衆国上院議員 の国鉄 のMLBドラフト の空軍 のNFL の登場キャラクター のナショナルリーグチャンピオンシップシリーズ の地理 の文化 のアメリカンリーグチャンピオンシップシリーズ の文学 の世界ラリー選手権 のニュース の海軍 の比較 の日本競馬 のオールナイトニッポンR の町名 の陸軍 の観光地 の女王 の議会 の科学 の自転車競技 のチーム記録 の警察 の促進に関する法律 の問題 の政変 のNBAドラフト のリスト の韓国シリーズ の宇宙飛行 の元素 の相撲 の年のラジオ の事件 のJSL のスーパーバイク世界選手権 の憲法 のユーロ硬貨 の電車 の戦争 の通り の兵器 のJリーグ の全日本F3選手権 のサッカー
今回のスクリプトや結果はgistにも置いてます。
https://gist.github.com/ikegami-yukino/8042385
ただ、これだけだとまだまだ不要見出し残ってるので、あとでまた何か書くかも。