Elasticsearch ウェブクローラー 基本編

Elasticsearch River Web —Webサイトのクローリング手順

Miyuki Endo
10 min readMay 8, 2014

--

Elasticsearch River Web とは

通常Elasticsearchは、用意されている様々なAPIを使いデータのインデックスを行います。そのためたとえば、企業サイトのサイト内検索をElasticsearchを使用して実現する場合は、Webサイトの全コンテンツをElasticsearchにインデックス可能なフォーマットにデータ化し、API経由でインデックするという方法が一般的と思われます。もともとDBなどでコンテンツ内容を管理していればその方法でも対応できるかもしれませんが実際対応するとなると結構面倒です。しかし、このRiver Webを使うとWebサイトをクローリングできるため、サイトの各ページを検索対象にしたい場合は大変便利です。

今回は、このElasticsearch向けWeb Crawlerプラグイン「elasticsearch-river-web」の基本的な使い方についてまとめてみたいと思います。

インストール

River Web Pluginは、2014年5月時点でElasticsearch1.1.1に対応しています。詳細はこちらで確認できます。
Elasticsearch1.1.1は事前にインストールしておきます。

Quartz plugin

River Webプラグインをインストールする前に「Quartz plugin」をインストールする必要があります。Quartz Pluginはスケジューラーなので、クローラーのスケジュール管理に使用されます。

$ bin/plugin --install org.codelibs/elasticsearch-quartz/1.0.1

River Web Plugin

Quartz Plugin をインストール後、River Web Plugin をインストールします。
2014年5月時点ではversion1.1.2が最新ですが、Issuesを見ると機能追加や改善が行われているので、度々確認してみると良いかもしれません。

$ bin/plugin --install org.codelibs/elasticsearch-river-web/1.1.2

インストールが出来ているか、Elasticsearchを起動して確認します。

$ curl -XGET 'localhost:9200/_nodes?pretty'

次の様に両方インストールされたことが確認できればOKです。

インストール済みプラグインの確認

インデックスの定義

Webクローリング用のインデックスを定義します。本当はマッピング定義に”analysis”の設定も入れたいのですが、まずはanalyzerなどの指定はしないで一通り進めてみたいと思います。
ちなみに、クローリングの設定前に必ずインデックスの定義を行います。
今回は自社HPをクローリングしてみたいと思うので、Indexを「websites」、Typeを「kwsite」として定義します。

$ curl -XPUT "localhost:9200/websites" -d '{
"mappings": {
"kwsite" : {
"dynamic_templates" : [
{
"url" : {
"match" : "url",
"mapping" : {
"type" : "string",
"store" : true,
"index" : "not_analyzed"
}
}
},
{
"method" : {
"match" : "method",
"mapping" : {
"type" : "string",
"store" : true,
"index" : "not_analyzed"
}
}
},
{
"charSet" : {
"match" : "charSet",
"mapping" : {
"type" : "string",
"store" : true,
"index" : "not_analyzed"
}
}
},
{
"mimeType" : {
"match" : "mimeType",
"mapping" : {
"type" : "string",
"store" : true,
"index" : "not_analyzed"
}
}
}
]
}
}
}'

〜 MEMO 〜
“store”は1.0以降(多分)、true / false の指定方法に変わったようです。(以前は “yes” / ”no”の指定でした。)
クローリング時、重複するURLの場合、古い方を消して新しい方をインデックスする設定(“overwrite”)をクローラー設定側で行う場合は、URLを必ず”index” : “not_analyzed” にします。

次のコマンドでマッピングの確認をします。設定した通りに返ってくればOKです。

$ curl -XGET 'localhost:9200/websites/_mapping/kwsite?pretty'

クローラー設定

次にクローリング情報を設定します。”river”を定義することでクローリングの設定ができます。

$ curl -XPUT 'localhost:9200/_river/kwsite/_meta' -d '{
"type" : "web",
"crawl" : {
"index" : "websites",
"url" : ["http://hp.knowledge-works.co.jp/", "http://alive.knowledge-works.co.jp/"],
"includeFilter" : ["http://hp.knowledge-works.co.jp/.*", "http://alive.knowledge-works.co.jp/.*"],
"maxDepth" : 3,
"maxAccessCount" : 200,
"numOfThread" : 5,
"interval" : 1000,
"overwrite" : true,
"userAgent" : "Elasticsearch Bot (hoge@example.xx)",
"robotsTxt" : false,
"target" : [
{
"pattern" : {
"url" : "http://hp.knowledge-works.co.jp/.*",
"mimeType" : "text/html"
},
"properties" : {
"title" : {
"text" : "title"
},
"body" : {
"text" : "div.gdl-page-item",
"trimSpaces" : true
},
"bodyAsHtml" : {
"html" : "body"
},
"tags" : {
"text" : "div.single-thumbnail-tag a",
"isArray" : true
},
"meta" : {
"attr" : "meta[name=description]",
"args" : ["content"]
}
}
},
{
"pattern" : {
"url" : "http://alive.knowledge-works.co.jp/.*",
"mimeType" : "text/html"
},
"properties" : {
"title" : {
"text" : "title"
},
"body" : {
"text" : "body"
},
"bodyAsHtml" : {
"html" : "body"
},
"meta" : {
"attr" : "meta[name=description]",
"args" : ["content"]
}
}
}
]
},
"schedule" : {
"cron" : "0 0 15 * * ?"
}
}'

詳しい設定情報は、elasticsearch-river-webのRegister Crawl Data のconfigurationに記載されています。

〜 MEMO 〜
“overwrite”の設定により、重複URLをクローリングした際、新しいドキュメントを有効にすることができます。
“userAgent”には、Botの名前やメールアドレス等をきちんと設定しておきます。
“robotsTxt”は、通常はいじらずにtrueで使用しますが、今回クローリングで弾かれてしまったため、自社サイトなのでいっかという思いでfalseに設定しました。自サイト以外をクローリングする場合はrobotsを尊重しないとダメですね。
“schedule” で、クローリングの開始時間を設定します。cronと同じ書き方です。ちなみに、スケジュールを変更する場合は、対象の_riverを一旦DELETEしてから、スケジュールを変更した_riverを作成します。

<追記>
“includeFilter”はクローリング対象(follow)のURLルールを(配列で複数指定可能)、 “target”.”pattern”.”url”はインデックス対象のURLルールを(複数指定する場合は”target”を配列で複数記述) 設定する。

次のコマンドで設定内容を確認します。

$ curl -XGET 'localhost:9200/_river/kwsite/_meta?pretty'

検索

scheduleに設定した時間が過ぎたら、クローリングの確認をします。
Elasticsearchのログにクローラーが辿ったURLが出力されるので、それはクローラーの形跡を確認するのに役立ちます。
ドキュメントを取得してみます。

$ curl -XGET "localhost:9200/websites/kwsite/_search?pretty" -d '{
"query":{
"match_all":{}
},
"fields":["url","title","tags","meta","method","body"],
"sort": ["url"],
"from":0,
"size":20
}'

こんな感じで結果が返ってきました。

検索結果

“maxAccessCount”を200に設定したのに、90件しかないということは、そもそも90ページしかサイトに存在しなかったのか、クローリングは200URLしたけどインデックス90しか出来なかったのか。この辺りは検証が必要そうですね。

まとめ

これでインデックス設定、クローラー設定、クローリング、検索と一通り行うことができました。
あとは実際サイト内検索として使用するために、日本語解析の設定だとか細かいマッピング定義、それからクローリング時間や間隔を調整すれば、サイトに適した検索が実現できるのではないでしょうか。

--

--