Elasticsearch ウェブクローラー PDF編

Elasticsearch River Web — PDFページのクローリング手順

Miyuki Endo
9 min readMay 19, 2014

前回の記事では、Elasticsearch River Webを使用したサイト (HTML) のインデックス、クローリング設定〜検索確認までの基本的な手順を紹介しました。今回は、多くのコーポレートサイトに存在する「PDF」をクローリング対象とし検索するための手順をまとめたいと思います。

必要なPluginのインストール

Mapper Attachments Type for Elasticsearch

PDFデータは、Elasticsearch標準のstringなどのフィールドtypeではなく、 ”attachment”というtypeを定義してインデックスします。
また、”attachment”は、PDFだけでなくMicrosoft OfficeやOpen Documentなどのフォーマットもbace64エンコードしてインデックスできます。(詳細はサポートしているドキュメントリストで確認できます。)
使用にはpluginのインストールが必要です。

$ bin/plugin -install elasticsearch/elasticsearch-mapper-attachments/2.0.0

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

$ curl -XGET ‘localhost:9200/_nodes?pretty’

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

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

インデックス・マッピング定義

Webクローリング用のインデックスを定義します。日本語解析のための設定は、「Elasticsearch 日本語の為のスキーマレス環境構築」を参考に設定済みのため、ここではAnalyzerなどの指定は入れずにインデックスを定義します。

$ curl -XPUT "localhost:9200/websites_ja" -d '{
"mappings": {
"siteA" : {
"properties" : {
"url" : {
"type" : "string",
"index" : "not_analyzed"
},
"method" : {
"type" : "string",
"index" : "not_analyzed"
},
"charSet" : {
"type" : "string",
"index" : "not_analyzed"
},
"mimeType" : {
"type" : "string",
"index" : "not_analyzed"
},
"pdf_attachment" : {
"type" : "attachment",
"fields" : {
"pdf_attachment" : {"index":"no", "include_in_all":true},
"title" : {"store":true},
"author" : {"store":true},
"name" : {"store":true},
"date" : {"store":true},
"keywords" : {"store":true},
"content_type" : {"store":true},
"content_length" : {"store":true},
"language" : {"store":true}
}
}
}
}
}
}'

〜 MEMO 〜
”pdf_attachment”

PDFデータを取込むためにこのプロパティを定義しています。
”pdf_attachement”フィールドにPDFコンテンツを、”title”以下のフィールドに各Meta情報をマッピングしています。
”pdf_attachment”フィールド:データサイズが大きくなるためno indexの設定をしています。しかし、フィールドを指定しない_allを使った検索ではコンテンツの内容も検索対象にしたいため、”include_in_all”をtrueに設定しています。
”title”以下のフィールド:”store”をtrueにすることで検索時に元データの取得が可能になります。設定しないとbase64encode されたデータのみが_sourceに保存されます。
検索結果一覧にコンテンツの内容も掲載したい場合や、highlightを使用したい場合は、”pdf_attachement”フィールドも”store”:trueに設定します。

クローリング定義

クローラー側の設定をします。
今回はいろいろ悩んだ末、港区の各種申請書類であるPDFを対象にクローリングし検索してみたいと思います。

$ curl -XPUT 'localhost:9200/_river/siteA/_meta' -d '{
"type" : "web",
"crawl" : {
"index" : "websites_ja",
"url" : ["http://www.city.minato.tokyo.jp/shinsesho/index.html"],
"includeFilter" : ["http://www.city.minato.tokyo.jp/shinsesho/.*",
"http://www.city.minato.tokyo.jp/shibamadochou/kurashi/todokede/.*",
"http://www.city.minato.tokyo.jp/shibamadosa/kurashi/todokede/.*"],
"maxDepth" : 3,
"maxAccessCount" : 50,
"numOfThread" : 5,
"interval" : 1000,
"overwrite" : true,
"userAgent" : "Elasticsearch Bot (<Mail Address>)",
"target" : [
{
"pattern" : {
"url" : "http://www.city.minato.tokyo.jp/.*.pdf",
"mimeType" : "application/pdf"
},
"settings" : {
"html" : false
},
"properties" : {
"pdf_attachment" : {"type" : "attachment"}
}
}
]
}
}'

〜 MEMO 〜
基本編と同様、重複するURLは”overwrite”で後勝ちにしています。
“userAgent”にはBot名やメールアドレスを設定しています。
“target”にPDFをクローリングするための設定を記述しています。
一度だけクローリングして確認するために”schdule”の設定は入れてません。

検索して確認する

クローリングが終わったらどのようにインデックスされているか検索して確認してみます。

まずは件数を取得。

$ curl -XGET "http://localhost:9200/websites_ja/siteA/_count?pretty"
インデックス件数の確認

17 件インデックスできているようです。
次に「住民票」をキーワードに検索してみます。

$ curl -XGET "http://localhost:9200/websites_ja/siteA/_search?pretty" -d' {
"query":{
"query_string":{
"query":"\"住民票\""
}
},
"fields":[
"url",
"pdf_attachment.title",
"pdf_attachment.author",
"pdf_attachment.name",
"pdf_attachment.date",
"pdf_attachment.keywords",
"pdf_attachment.content_type",
"pdf_attachment.content_length",
"pdf_attachment.language"
]
}'

〜 MEMO 〜
今回(Analyze等で)設定した内容では、“query”:”住民票” と検索すると 「住民」と「票」に分かれてしまい、query側で”default_operator” を”AND”にすると、離れた場所に記載されている「住民」と「票」のドキュメントもヒットしてしまうため、「住民票」というphraseで検索するようdouble quotesで囲いました。
“fields”を指定しないと”_source”に保存されているbase64encodeされたデータが返ってきて見づらくなります。

キーワード「住民票」の検索結果

こんな感じで検索結果が返ってきました。確認したところ、ばっちりTitleやPDFの内容に「住民票」が含まれているドキュメントでした。

まとめ

PDFドキュメントについてもマッピング定義、クローリング、検索まで行うことができました。
これで、HTMLとPDFが混在したクローリング設定もできそうです。
サイト内検索の実現へ向けてまた一歩前進です!

--

--