雑文発散

«前の日記(2014-11-11) 最新 次の日記(2014-11-13)» 編集
過去の日記

2014-11-12 [長年日記]

[Elasticsearch] Elasticsearch で Web のクローリングを行なう

Elasticsearch の情報をいろいろ探しているうちに「Elasticsearch ウェブクローラー 基本編」という記事に出会った。

全文検索のエンジンのくせに、自分からデータを取りに行ってストアするとか面白いことするな!と思ったんだけど、全文検索が故にそういう用途のニーズも多いんだろうな。

ということで、この日記に対してクローリングを行なって、全文検索できるような仕組みを作ってみる。

Elasticsearch や Kibana は「Fluentd + Elasticsearch + Kibana での解析の構成を考える」あたりで構築したものを流用する。

基本的には、前述の「ウェブクローラー基本編」の記事をほぼそのまま踏襲させて頂いたのだけど、若干変更してみたところもあるので、こちらにも記録しておく。

プラグインのインストール

Web のクローリングを実現するには、2つのプラグインを Elasticsearch へインストールする必要があるとのこと。

Quartz プラグインのインストール
% sudo /usr/share/elasticsearch/bin/plugin --install org.codelibs/elasticsearch-quartz/1.0.1
-> Installing org.codelibs/elasticsearch-quartz/1.0.1...
[snip]
Installed org.codelibs/elasticsearch-quartz/1.0.1 into /usr/share/elasticsearch/plugins/quartz
River Web プラグインのインストール
% sudo /usr/share/elasticsearch/bin/plugin --install org.codelibs/elasticsearch-river-web/1.3.1
-> Installing org.codelibs/elasticsearch-river-web/1.3.1...
[snip]
Installed org.codelibs/elasticsearch-river-web/1.3.1 into /usr/share/elasticsearch/plugins/river-web

Elasticsearch の再起動

プラグインをインストールしても、実行中の Elasticsearch は認識してくれないので再起動してやる。あまり詳しく調べてないけど、restart だとうまく起動してくれなかったので、stopstart の方が安全なのかな?

ここら辺は、実運用するとなったら気にしたいところ。

% sudo /etc/init.d/elasticsearch stop
[ ok ] Stopping Elasticsearch Server:.
% sudo /etc/init.d/elasticsearch start
[ ok ] Starting Elasticsearch Server:.

プラグインの確認

プラグインを認識しているかの確認。_cap API でプラグインの情報を確認すれば良いようだ。

% curl -XGET 'http://localhost:9200/_cat/plugins'
X-wing WebPlugin    NA j
X-wing QuartzPlugin NA j

WebPlugin と QuartzPlugin という名前が見える。無事にインストールされた様子。ちなみに X-wing というのは、この実験をしている Elasticsearch の node 名なので深い意味はない。

マッピングの登録

Elasticsearch のインデックス名(DB 名みたいなもの)は、webindex にした。タイプ名(テーブル名みたいなもの)は、suzuki_tdiary_net にした。

mappings.json

本当なら日本語記事のアナライズ用に kuromoji を入れるべきなんだけど、ここでは省略。たぶん、後でやり直す。

マッピングデータの投入
% curl -XPUT 'http://localhost:9200/webindex' -d @mappings.json
{"acknowledged":true}

クローラー用の設定を追加

クローラー用の設定を作って投入する。

river.json

設定用に JSON ファイルを作った。

いろいろ試行錯誤にアクセスログを見ながら気がついたのは、JavaScript や画像ファイルもクロールしようとしていたこと。なので、excludeFilter/image//js/ を外したりした。

あと、ちょっとハマったのは、schedule の設定。River Web の GitHub リポジトリに「Cron format to start a crawler.」と書かれていたので、普通に書いたつもりだったんだけど、どうもうまく動かなくて悩んでいた。

で、Quartz プラグインの Cron Format のページをよくよく見てみると、最初に「Seconds」というフィールド名が書かれていた。秒も指定できるのね。。。

Linux の cron には秒の指定が無いので、いつものように「分 時 * * *」という設定をしていたつもりで「秒 分 * * *」を指定していたのであった。

クローラー設定の投入
% curl -XPUT 'http://localhost:9200/_river/suzuki_tdiary_net/_meta' -d @river.json
{"_index":"_river","_type":"suzuki_tdiary_net","_id":"_meta","_version":1,"created":true}
データの確認

URL に pretty を付けても _source の部分は綺麗にしれくれなかったので、コマンド出力結果の JSON を Emacs の M-x json-mode-beautify を使って加工している。

% curl -XGET 'http://localhost:9200/_river/suzuki_tdiary_net/_meta?pretty'

動作の確認

これで指定時刻にクローラーが suzuki.tdiary.net へアクセスしに行くはず。これはアクセスログを見て、UserAgent が Elasticsearch Bot (suzuki.tdiary.net) のアクセスの有無で判別できる。

Elasticseach 側にデータが入っているのかは、_catcount を見てみると良いのかも。

% curl -XGET 'http://localhost:9200/_cat/count/webindex?v'
epoch      timestamp count
1415795152 21:25:52  204

なんらかのデータは入っているようなので、今度は <title>elasticsearch という文字列が入っているデータを検索してみる。

% curl -XGET 'http://localhost:9200/webindex/suzuki_tdiary_net/_search?q=title:elasticsearch&fields=title&pretty=true'

ちゃんと返ってきた。

これで Elasticsearch で Web クローリングができることは確認できた。ちなみに、クローリング中のプロセス状況を見ていたんだけど、特にクローラーのプロセスが立ち上がる訳ではないようだ。

netstat で suzuki.tdiary.net へのアクセスを確認したところ、Elasticsearch Server と同じプロセスから通信が行なわれていた。プロセスじゃなくスレッドの世界なのね。

それから、このクローラーが以前インストールした mod_evasive に DoS 判定されたので、DOSWhitelist の設定に Elasticserver が動いている IP アドレスを追加した。

なんとなく動いたので、後は kuromoji を入れて、日本語の検索を賢くしたりすればいいかな。もうちょっと続けていじってみよう。