はじめに
この記事は、
のおおよその続編。
また、
の親戚記事です。
一言で言うと、「ナレッジインデックス(仮称)」というものを考えて、こいつの有効性を(実証は難しいものの)いくつか試してみるというものになります。
- はじめに
- アンサイクロペディアから東京エリアナレッジインデックス(仮称)生成
- wikipediaから東京エリアナレッジインデックス(仮称)生成
- linuxコマンドラインのスクリプトの参考にしたリンク
- アンサイクロペディア
- wikipedia
- 参考文献リンク
使用したElasticsearchのバージョンは6.4です。
アンサイクロペディアとwikipediaから「東京関係」の解説記事を抜き出した上、Elasticsearchにまるっと放り込んで(これが別記事でナレッジインデックスと呼んでいるもの)、東京の地理に関する検索語(例: 上野)に関連するワードがが得られるかやって見るというものです。 (ここだけ見ると、Significant t... の当たり前の機能じゃん...ですが。)
wikipediaのデータをElasticsearchにインポートする正攻法は他のブログで有用な記事を皆さんが作成されています。この記事はそれらと少し趣がことなりますので、Google検索等で流れついた方は、ご容赦ください。また、自分の主張を卑下するわけではありませんが、この記事で言うナレッジインデックス(仮称)は少々名前負けしています。
アンサイクロペディアから東京エリアナレッジインデックス(仮称)生成
1) mapping設定します。
PUT your_index5 { "mappings": { "_doc": { "dynamic_templates": [ { "dtmpl": { "match_mapping_type": "*", "match": "*_ja", "mapping": { "analyzer": "my_kuromoji", "fielddata":true } } } ] } }, "settings": { "analysis": { "analyzer": { "my_kuromoji": { "type": "custom", "tokenizer": "kuromoji_tokenizer", "mode": "search", "char_filter": [ "icu_normalizer", "kuromoji_iteration_mark" ], "filter": [ "kuromoji_baseform", "kuromoji_part_of_speech", "ja_stop", "lowercase", "kuromoji_number", "kuromoji_stemmer" ] } } } } }
2) アンサイクロペディアのデータをダウンロードします。
http://download.uncyclomedia.org/
http://download.uncyclomedia.org/ja-wiki.xml.gz
展開すると、12Gぐらいありました。
3) indexに入れるための、東京に関するデータを抽出します。
データを抜き出すためのツールを作成しました。
この、
# encoding: utf-8 # wiki_simple_ext.rb : # アンサイクロペディアのデータの地域の説明はおおよそ次のようなXMLのスキーマになっているようだ。 # なので目的の情報を持ってそうな、*印部分の要素を1行ずつ処理する。 # # * page # * title # * revision # * {東京} もしくは {XXX} # revision # {東京} もしくは {XXX} # ... entry = "" tokyo = false revision = 0 STDIN.each_line do |l| if l.match(/<page>/) then puts entry + "</page>" if tokyo == true entry = "" tokyo = false revision = 0 end revision = revision + 1 if l.match(/<revision>/) entry = entry + l if revision <= 1 tokyo = true if l.match(/\{\{(東京|東京都区部|東京都の鉄道駅|東京都の自治体|大阪)\}\}/) end puts entry + "</page>" if tokyo == true
を wiki_simple_ext.rbとして、
cat ja-wiki.xml | ruby wiki_simple_ext.rb > ja-wiki-tokyo.xml
export META='{"index":{}}'; cat ja-wiki-tokyo.xml | tr '"' ' ' | tr '\n' ' ' | tr '{' ' ' | tr '}' ' ' | sed 's/<\/page>/<\/page>"\'$'\n/g' | sed 's/<title>/"title_ja":"/' | sed 's/<\/title>/","content_kw":"/g' | sed 's/<[^>]*>//g' | sed '/^ *$/d' | ruby -nle 'puts ENV["META"] + "\n{" + $_ + "}"' > ja_wiki_tokyo.json
で、バルクロードに向いた次の形式のJSONファイルにしてやります。
{"index":{}} { "title_ja":"葛飾区", "content_ja":"XXXXXXXXXX" }
4) バルクロード
ja_wiki_tokyo.json を次のコマンドでバルクロードします。 (今気づきましたが、アドホック手順とはいえ、ファイル名に規則性がなくて分かりづらいですね。)
curl -H "Content-type: application/x-ndjson" -X POST localhost:9200/your_index5/_doc/_bulk?refresh --data-binary @ja_wiki_tokyo.json
取り漏れが何件かあったようですが、ひとまずインポートできました。
5) significant_text*2で検索してみます。
POST /your_index5/_search { "size": 0, "query": { "match": { "content_ja": { "query": "上野", "operator": "and" } } }, "aggs": { "titlegroup": { "terms": { "field": "title_ja" }, "aggs": { "tokuchougo": { "significant_text": { "field": "content_ja" } } } } } }
返ってきました↓。
"key": "上野", "bg_count": 14 "key": "東北", "bg_count": 7 "key": "ターミナル", "bg_count": 5 "key": "東北新幹線", "bg_count": 4 "key": "東北本線", "bg_count": 4 "key": "新幹線", "bg_count": 4 "key": "常磐線", "bg_count": 5 "key": "常磐", "bg_count": 5 "key": "止める", "bg_count": 3 "key": "起点", "bg_count": 3 "key": "京成電鉄", "bg_count": 3 "key": "何者", "bg_count": 3 "key": "運転", "bg_count": 3 "key": "京浜東北", "bg_count": 3 "key": "本線", "bg_count": 8 "key": "列車", "bg_count": 6 "key": "京浜", "bg_count": 4 "key": "御徒", "bg_count": 4 "key": "始発駅", "bg_count": 4 "key": "更に", "bg_count": 4
気持ちは分からんでもないが.... というところです。
ちなみに、アンサイクロペディアをチョイスしたのは、「危険」や「眠らない街」でSignificant_textで検索して「新宿」がヒットしたりしないかな〜、だと面白いな〜と考えたからですが、そこまで都合はよくありませんでした。
一応aggsをネストしたものもやってみましたが、結果は略します。(このaggsのネストに深い意図はないです。)
POST /your_index5/_search { "size": 0, "query": { "match": { "content_ja": { "query": "上野", "operator": "and" } } }, "aggs": { "titlegroup": { "terms": { "field": "title_ja" }, "aggs": { "tokuchougo": { "significant_text": { "field": "content_ja" } } } } } }
wikipediaから東京エリアナレッジインデックス(仮称)生成
なんとなくとっつきやすかったのでアンサイクロペディアの方を先にやりましたが、最初から、より体系的に記述されているであろうwikipediaでよかったような気がしてきました...
多分同じようなフォーマットと思われるので(実際、今回やりたいことの範囲ではおおよそ同じスキーマ形式でした)同じ手順でやります。
1) wikipediaデータのダウンロード
https://dumps.wikimedia.org/jawiki/
https://dumps.wikimedia.org/jawiki/20181201/jawiki-20181201-pages-meta-current.xml.bz2
展開すると16GBぐらいでした。
2) wikipediaのデータの東京関連データ抽出
冒頭の絞り込みrubyツールをwikipedia用に見直しました。こいつにwikipediaのxmlを食らわせて、 jawiki-mini.xmlというファイルを作ります。
# encoding: utf-8 # * page # * title # * revision # * [Category:東京都の特別区... # revision # [Category:東京都の特別区... # ... entry = "" tokyo = false revision = 0 STDIN.each_line do |l| if l.match(/<page>/) then puts entry + "</page>" if tokyo == true entry = "" tokyo = false revision = 0 end revision = revision + 1 if l.match(/<revision>/) entry = entry + l if revision <= 1 tokyo = true if l.match(/\[Category:(東京都の特別区|東京都の市町村|東京都交通局の鉄道駅|..区の鉄道駅|...区の鉄道駅)\]/) end puts entry + "</page>" if tokyo == true
中途半端に同じようなコードを量産してしまいました。これなら有志の方が作成されているwikipediaのXMLをパースするツール等を利用させてもらえばよかったようにも思いました。が、ひとまず続けます。
バルクロード用のJSONファイルを作ります。
export META='{"_____":{}}'; cat jawiki-mini.xml | tr '"' ' ' | tr '\n' ' ' | tr '{' ' ' | tr '}' ' ' | sed 's/<\/page>/<\/page>"\'$'\n/g' | sed 's/<title>/"@@@":"/' | sed 's/<\/title>/","%%%":"/g' | sed 's/<[^>]*>//g' | sed '/^ *$/d' | ruby -nle 'puts ENV["META"] + "\n{" + $_ + "}"' | sed 's/Category:/...:/g' | tr -d '[0-9A-Za-z]' | sed 's/@@@/title_ja/g' | sed 's/%%%/content_ja/g' | sed 's/_____/index/g'
ここまで書いて、ひょっとして簡易なXMLぐらいなら、サクッと読み込んでくれるkibanaとかlogstashとかの仕組みがあるのではと思いましたが、実のところよく知らないので、この方法に徹しました。
つづきます。
4) バルクロードします
JSONファイルをバルクロードします。
curl -H "Content-type: application/x-ndjson" -X POST localhost:9200/your_index_spot/your_type_spot/_bulk?refresh --data-binary @jawiki-mini.json
5) significant_textで検索してみます。
アンサイクロペディアの例と同じで、「上野」での検索です。
返ってきたのはコレ↓
"key": "上野", "bg_count": 130 "key": "京成", "bg_count": 102 "key": "台東", "bg_count": 47 "key": "御徒", "bg_count": 32 "key": "御徒町", "bg_count": 29 "key": "成田", "bg_count": 82 "key": "千住", "bg_count": 93 "key": "都営", "bg_count": 363 "key": "上野公園", "bg_count": 23 "key": "成田空港", "bg_count": 67 "key": "秋葉原", "bg_count": 51 "key": "集計", "bg_count": 64 "key": "浅草", "bg_count": 94 "key": "区内", "bg_count": 104 "key": "葉", "bg_count": 60 "key": "日間", "bg_count": 55 "key": "江戸", "bg_count": 86 "key": "恩賜", "bg_count": 23 "key": "松坂屋", "bg_count": 21 "key": "千葉", "bg_count": 46
悪くない気がする。
結構「上野」感の雰囲がでているかもしれません。
significant .... はそういうものだから当たり前のところもありますが、一文字のものは取り除くとしたらそのまま使えるのでは?と思わせるところがありますね。
linuxコマンドラインのスクリプトの参考にしたリンク
http://taichiw.hatenablog.com/entry/2012/04/06/102650
https://qiita.com/kkdd/items/725e53572bc69e4b51b7
https://orebibou.com/2015/07/sedコマンドで覚えておきたい使い方12個/
アンサイクロペディア
https://ansaikuropedia.org/wiki/%E3%83%A1%E3%82%A4%E3%83%B3%E3%83%9A%E3%83%BC%E3%82%B8
wikipedia
https://dumps.wikimedia.org/backup-index.html
http://koiroha.blogspot.com/2017/04/how-to-get-wikipedia-dump-as-plaintext.html
http://nonbiri-tereka.hatenablog.com/entry/2015/10/12/104800
参考文献リンク
http://komaken.me/blog/2018/01/16/elasticsearch-aggregationに任意の値を含める/ [Elasticsearch] aggregationに任意の値を含めるhttps://github.com/logstash-plugins/logstash-patterns-core/blob/master/patterns/grok-patterns
*1:※ ja-wiki.xmlはアンサイクロペディアの全件データです。
*2:significant_termsと言いましたが、実際はtextにしました