クローラガイド

Copyright (C) 2004-2007 Mikio Hirabayashi
Last Update: Tue, 06 Mar 2007 12:05:18 +0900

目次

  1. はじめに
  2. チュートリアル
  3. クローラコマンド
  4. Web検索エンジンの実現

はじめに

このガイドでは、Hyper EstraierのWebクローラの詳細な使い方を説明します。ユーザガイドP2Pガイドをまだお読みでない場合は先にそちらに目を通しておいてください。

estcmdだとローカルのファイルシステム上にある文書(ファイル)を対象としたインデクシングしかできません。NFSやSMB等を用いてファイルシステムをリモートマウントすれば別のマシンにある文書をインデクシングすることもできますが、不特定対数のWebサイトの文書を扱おうとするとそうもいきません。wgetなどのクローラで文書を集めて来てローカルに保存してからインデクシングすることも考えられますが、ディスク容量の問題や更新頻度の問題などがあります。

Web上のリンクを辿って文書を収集することをWebクローリングと言い、そのプログラムをWebクローラと言います。Hyper Estraierに付属のWebクローラestwaverを使うと、任意のWebサイトの文書を直接的にインデックスに登録することができます。

estwaverは賢いクローラです。深さ優先探索や幅優先探索のような単純なアルゴリズムでなく、文書の内容を判断して関連するものを優先的に辿って行きます。種文書として指定した文書は、探索の起点になるとともに、類似度判定の材料にもなります。類似検索と同じ要領で種文書のベクトルの和に対する類似度を算出し、それが高い文書のリンク先を優先的に辿ります。


チュートリアル

estwaverも多彩な機能をもっていますが、基本的な使い方は単純です。実際に動かしながら使い方を身につけていきましょう。

基本的な使い方

クローラを動かす準備として、以下のコマンドを実行してクローラルートディレクトリを作ってください。クローラルートディレクトリとは、クローラの動作に必要な設定ファイルなどを格納するディレクトリツリーのトップのことです。

estwaver init casket

デフォルトではHyper Estraierのホームページなどを起点としてクローリングを行うように設定されています。casket/_confを編集すれば、設定を変更することができます。とりあえずはseedという項目を編集して、巡回の起点となるURLに好きなサイトのURLを指定してください。「|」の前の部分は類似度判定の重み付けなのですが、とりあえずは「1.0」にしておけばよいでしょう。なお、プロクシを使わないとWebが見られない環境では、proxyhostproxyportにプロクシのホスト名とポート番号を設定することも必要です。また、日本語のサイトを優先して巡回したい場合はlanguage1にするとよいでしょう。例えば以下のように設定します。

seed: 1.0|http://www.asahi.com/
seed: 1.0|http://www.yomiuri.co.jp/
seed: 1.0|http://www.mainichi.co.jp/
...
proxyhost: proxy.yourdomain.ad.jp
proxyport: 8080
...
language: 1
...

それでは、クローラを動かしてみましょう。以下のコマンドを実行してください。

estwaver crawl casket

すると、文書が続々と取得されてインデックスに登録されていきます。停止させたい場合は端末でCtrl-Cを入力してください。しばらく待つと停止します。

クローリングが終った時には、クローラルートディレクトリの中に_indexというディレクトリができています。これがestcmd等で利用できるインデックスです。作成されたインデックスを使って検索を行ってみましょう。

estcmd search -vs casket/_index "hyper estraier"

中断したクローリングを再開するには、再びestwaver crawlを実行します。

estwaver crawl casket

-revisitオプションをつけてestwaver crawlを実行すると、既にインデックスに登録した文書のみを対象にして再巡回を行い、更新された文書をインデックスに反映させたり、削除された文書の情報をインデックスから削除したりできます。

estwaver crawl -revisit casket

-revcontオプションをつけてestwaver crawlを実行すると、既存の文書の再巡回を行ってから、他の文書のクローリングを続行します。-restartオプションをつけてestwaver crawlを実行すると、クローリングを最初からやり直して、Web上で更新された文書の内容をインデックスに反映させることができます。通常の運用では、-revcontオプションで定期的にインデックスを更新するのがよいでしょう。

イントラネットでの利用

企業や学校などのイントラネットでいくつかのWebサイトを運営している場合にもクローラを使ってインデクシングをすると便利です。イントラネットの文書からも外部(インターネット)へのリンクが張ってあることが考えられるので、casket/_confallowrxを編集して巡回先を制限します。例えば、estraier.ad.jpドメインのみを巡回する場合は以下のようにします。

seed: 1.0|http://www.estraier.ad.jp/
seed: 1.0|http://intra.estraier.ad.jp/
...
allowrx: ^http://[^/]*\.estraier.ad.jp/
...

ノードサーバへの登録

数百万件以上の文書を対象にしたい場合は、巡回した文書を全て単一のインデックスに登録していくのはスケーラビリティの観点から現実的ではありません。また、クローラが動作している間はインデックスがロックされてしまうという欠点もあります。P2P機構のノードサーバに文書を登録するとその問題を解決できます。それには、casket/_confnodeservを編集して、登録先のノードサーバを指定します。例えば、http://foo.estraier.ad.jp:1978/node/node1http://bar.estraier.ad.jp:1978/node/node2http://baz.estraier.ad.jp:1978/node/node3の3つのノードサーバに分散して登録する場合は、以下のようにします。「|」の前の部分はノードサーバにつけるIDなのですが、各々がユニークになるように適当な番号を指定してください。「admin:admin」の部分にはノードサーバに接続する際のユーザ情報を指定してください。

nodeserv: 1|http://admin:admin@foo.estraier.ad.jp:1978/node/node1
nodeserv: 2|http://admin:admin@bar.estraier.ad.jp:1978/node/node2
nodeserv: 3|http://admin:admin@baz.estraier.ad.jp:1978/node/node3

複数のノードサーバを指定すると適当な件数毎に分散して登録されるので、検索する際にはノードサーバのメタ検索機能を利用することになります。


クローラコマンド

ここでは、Web上の文書を対象としたインデックスを作るためのコマンドestwaverの詳細な仕様を説明します。

書式

estwaverは多くのサブコマンドの集合体です。サブコマンドの名前は第1引数で指定されます。その他の引数はサブコマンドの種類に応じて解釈されます。rootdirという引数はクローラルートディレクトリです。クローラルートディレクトリとは、クローラの動作に必要な設定ファイルなどを格納するディレクトリツリーのトップのことです。

estwaver init [-apn|-acc] [-xs|-xl|-xh] [-sv|-si|-sa] rootdir
クローラルートディレクトリを作成します。
-apnをつけると、全ての言語をN-gram法で処理します。
-accをつけると、N-gram法の代わりに文字種分類法を利用します。
-xsをつけると、50000件未満の文書を登録することを想定してインデックスを作成します。
-xlをつけると、300000件以上の文書を登録することを想定してインデックスを作成します。
-xhをつけると、1000000件以上の文書を登録することを想定してインデックスを作成します。
-svをつけると、スコア情報を破棄します。
-siをつけると、スコア情報を32ビットの数値として記録します。
-saをつけると、スコア情報をそのまま保存した上で検索時に調整されないようにマークします。
estwaver crawl [-restart|-revisit|-revcont] rootdir
クローリングを開始します。
-restartをつけると、以前に停止した状態を無視して種文書からクローリングをやり直します。
-revisitをつけると、以前に収集した文書の再取得のみを行います。
-revcontをつけると、以前に収集した文書の再取得を行った後にクローリングを継続します。
estwaver unittest rootdir
ユニットテストを行います。
estwaver fetch [-proxy host port] [-tout num] [-il lang] url
単一の文書を取得します。
urlは取得する文書のURLを指定します。
-proxyはプロクシのホスト名とポート番号を指定します。
-toutはタイムアウトの時間を秒単位で指定します。
-ilは文字コードの判定で優先される言語を指定します。デフォルトは英語です。

全てのサブコマンドは、処理が正常に終了した場合には0を、そうでない場合は1を終了ステータスにします。起動中のクローラに1(SIGHUP)、2(SIGINT)、3(SIGQUIT)、15(SIGTERM)のどれかのシグナルを送ることにより、データベースを閉じて正常終了させることができます。

クローラルートディレクトリの構成

クローラルートディレクトリは以下のファイルやディレクトリを格納しています。

設定ファイル

設定ファイルは、変数名と値を「:」で区切った形式の行を並べたものです。デフォルトでは、設定ファイルは以下のような内容になっています。

seed: 1.5|http://fallabs.com/hyperestraier/uguide-en.html
seed: 1.0|http://fallabs.com/hyperestraier/pguide-en.html
seed: 1.0|http://fallabs.com/hyperestraier/nguide-en.html
seed: 0.0|http://fallabs.com/qdbm/
proxyhost:
proxyport:
interval: 500
timeout: 30
strategy: 0
inherit: 0.4
seeddepth: 0
maxdepth: 20
masscheck: 500
queuesize: 50000
replace: ^http://127.0.0.1/{{!}}http://localhost/
allowrx: ^http://
denyrx: \.(css|js|csv|tsv|log|md5|crc|conf|ini|inf|lnk|sys|tmp|bak)$
denyrx: \.(zip|tar|tgz|gz|bz2|tbz2|z|lha|lzh)(\?.*)?$
denyrx: ://(localhost|[a-z]*\.localdomain|127\.0\.0\.1)/
noidxrx: /\?[a-z]=[a-z](;|$)
urlrule: \.est${{!}}text/x-estraier-draft
urlrule: \.(eml|mime|mht|mhtml)${{!}}message/rfc822
typerule: ^text/x-estraier-draft${{!}}[DRAFT]
typerule: ^text/plain${{!}}[TEXT]
typerule: ^(text/html|application/xhtml+xml)${{!}}[HTML]
typerule: ^message/rfc822${{!}}[MIME]
language: 0
textlimit: 128
seedkeynum: 256
savekeynum: 32
threadnum: 10
docnum: 10000
period: 10000s
revisit: 7d
cachesize: 256
#nodeserv: 1|http://admin:admin@localhost:1978/node/node1
#nodeserv: 2|http://admin:admin@localhost:1978/node/node2
#nodeserv: 3|http://admin:admin@localhost:1978/node/node3
logfile: _log
loglevel: 2
draftdir:
entitydir:
postproc:

それぞれの変数の機能を以下に示します。

allowrxdenyrxnoidxrxは記述した順番に解釈されます。また、正規表現における英字の大文字と小文字は区別されません。

巡回戦略

設定ファイルのstrategyという項目では、リンクを巡回する際の戦略を指定することができます。バランス戦略、深さ優先戦略、幅優先戦略、類似度優先戦略から選ぶことができます。

バランス戦略では、Webクローラとして最も適切であろうという振舞いをします。類似度優先をベースに、多数のサイトから種文書の内容に近い文書を効率良く集められるように調整をします。ブログ等のサイト内リンクに捕らわれて同じような文書ばかり集めたり特定のサイトに高いに負荷を与えたりしないように、他のサイトへのリンクに移動しやすいようにします。類似度優先戦略は、そのような調整をしないで類似度のみで巡回先を決定します。

深さ優先戦略と幅優先戦略は、一般的なツリー構造の探索アルゴリズムとしての深さ優先探索や幅優先探索とほぼ同じ振舞いをします。深さ優先はメモリ使用量を抑えられるという利点がありますが、ブログ等のサイト内リンクに捕らわれる可能性が高いので、不特定多数のサイトを巡回する用途には向きません。幅優先探索は多様なサイトから文書を集められるという利点がありますが、巡回する範囲があまりに広くなるので、これも不特定多数のサイトを巡回する用途には向きません。無作為戦略は巡回先の優先度を無作為に決定するので特定のサイトに負荷が集中しにくいという利点がありますが、幅優先探索と同じ欠点があります。なお、マルチスレッドで動くので、深さ優先戦略は完全な深さ優先探索にはならず、スレッド数の分だけ幅が出て来ます。完全な深さ優先探索をしたい場合はスレッド数を1にしてください。

特定のサイトの文書を全て集めるならば、どの戦略を使っても結果は同じです。とはいえ、メモリ使用量を抑えたいならば深さ優先戦略を使い、ブログ等のWebアプリケーションがある場合に備えるならば幅優先戦略か無作為戦略を使うとよいでしょう。

あるサイトに関連する文書を集めたい場合に、そのサイトの全てのページを指定するのが面倒な場合は、設定ファイルのseeddepthの値を増やすと便利です。seedに指定したURLからの指定したホップ数以内で到達できる文書が全て種文書になります。

フィルタプログラム

typeruleでは、「{{!}}」の後に任意のフィルタプログラムのコマンドを書くことができます。フィルタプログラムの仕様はestcmd gatherの「-fx」オプションと同じで、第1引数に対象文書のパス、第2引数に出力先のパスが渡されて呼び出されます。例えばPDF文書を処理するには以下のように指定します。

typerule: ^application/pdf${{!}}H@/usr/local/share/hyperestraier/filter/estfxpdftohtml

ファイルの保存と後処理

設定ファイルのdraftdirentitydirという項目を指定した場合、クローラが取得した文書の文書ドラフトや実体データのファイルをそのディレクトリが保存されます。さらに、postprocを指定すると、個々の文書を取得する度に、指定したコマンドが呼び出して後処理を行うことがれます。第1引数には保存した文書ドラフトのファイルのパスが、第2引数には保存した実体データのファイルのパスが渡されます。draftdirentitydirを指定しないでpostprocのみを指定した場合、テンポラリファイルが作成されてそのパスが引数として渡されます。

例えば、取得した文書をメールで送信するには、以下のようなシェルスクリプトを作って、そのコマンド名をpostprocに指定します。

#! /bin/sh
address="mikio@estraier.ad.jp"
url=`sed -n -e '/^@uri/ s/^@uri=// p' "$1"`
uuencode "$2" entity.dat | mail -s "[estwaver] $url" "$address"

適当な後処理のコマンドを用いれば、estwaverをHyper Estraier以外の検索システムの収集エージェントとして用いることができます。文書管理システムのフロントエンドとして使ってもよいでしょう。後処理のみを行ってHyper Estraierのインデックスに文書を入れる必要がない場合は、設定ファイルのnoidxの値を^http://などとしてください。


Web検索エンジンの実現

Hyper Estraierのマニュアル群をここまで読み進めてくれたあなたは偉い! ついにWeb検索エンジンを構築する時が来ました。誰でも自分のWeb検索エンジンを持てるようにするという、Hyper Estraierの目標がここに結実します。ここではそのためのノウハウを説明します。

インデックス用ノードサーバの準備

まずは、インデックスを管理するノードサーバを構築します。できるだけ大量の文書をできるだけ高速に検索するには、できるだけ多くのコンピュータで分散処理をさせた方が有利なのは言うまでもありませんが、とりあえずはPC1台でもWeb検索エンジンは実現できます。

PC1台で運用する場合にも、複数のノードサーバを用いた方がインデクシングの効率がよくなります。また、個々のノードサーバは別々のノードマスタ上で動かした方が効率がよくなります。その理由は、マルチプロセッサやマルチコアプロセッサの恩恵が受けやすくなることと、あるノードサーバがキャッシュをフラッシュしている間に別のノードサーバに登録先を割り振って処理速度の低下を抑止できることです。

ここでは、「ortho.estraier.ad.jp」「para.estraier.ad.jp」「meta.estraier.ad.jp」という3台のPCを所有していることを想定します。それぞれ1GBの実メモリを搭載しているとします。それぞれに1つずつノードマスタとノードサーバを配置することにしましょう。以下に作業例を示しますが、orthoparametaで同様の作業をしてください。

mkdir -p /home/mikio/var
cd /home/mikio/var
estmaster init master

適当なエディタで/home/mikio/var/master/_confを開いて、cachesizeの値を512にしてください。実メモリの搭載量が1GBならば、その半分くらいの容量のキャッシュを使うのが望ましいです。

ノードマスタをデーモンとして起動します。

estmaster start -bg master

ノードマスタのUI(Webブラウザでhttp://ortho.estraier.ad.jp:1978/master_uiなどに接続)を使って、管理者ユーザを設定します。ここではユーザ名が「mikio」で、パスワードが「oikim」ということにします。また、ノードサーバを作ります。ここでは名前を「child」とし、ラベルはホスト名をつけることにします。

メタ検索用ノードサーバの準備

orthoparametaの各ホストにノードサーバを構築したら、それらにメタ検索をするための親ノードを別に作ります。ここではorthoのノードマスタに作ることにして、名前は「parent」でラベルは「estraier.ad.jp」をつけることにします。

親ノードから各々の子ノードにリンクを張ります。この作業はどのホスト上で行っても構いません。

estcall setlink -auth mikio oikim http://ortho.estraier.ad.jp:1978/node/parent \
  http://ortho.estraier.ad.jp:1978/node/child ortho 10000
estcall setlink -auth mikio oikim http://ortho.estraier.ad.jp:1978/node/parent \
  http://para.estraier.ad.jp:1978/node/child para 10000
estcall setlink -auth mikio oikim http://ortho.estraier.ad.jp:1978/node/parent \
  http://meta.estraier.ad.jp:1978/node/child meta 10000

うまく設置できているか確認するために、親ノードの検索用ユーザインターフェイス(http://ortho.estraier.ad.jp:1978/node/parent/master_ui)に接続してください。そこで、「link#1: ortho」「link#2: para」「link#3: meta」の3つのリンクが表示されているはずです。それぞれのリンクを選択してみて、それぞれのノードサーバのユーザインターフェイスに進めるかどうかも確認してください。なお、親ノードから間違ってリンクを張ってしまった場合は、10000の部分を-1に変えてestcall setlinkを実行してリンクを消してください。

クローラの準備

クローラはmetaで動かすことにします。クローラ用のディレクトリを設置します。

cd /home/mikio/var
estwaver init waver

適当なエディタで/home/mikio/var/waver/_confを開いて、seedに値に種文書の重み付けとURLを指定してください。プロクシを使う場合はproxyhostproxyportも指定してください。また、日本語のサイトの文字コードの認識率を上げるために、languageも設定した方がいいでしょう。そして、取得した文書の登録先のノードも指定します。

seed: 1.5|http://fallabs.com/hyperestraier/
seed: 1.0|http://fallabs.com/estraier/
seed: 0.5|http://www.namazu.org/
...
proxyhost: proxy.estraier.ad.jp
proxyport: 3128
...
language: 1
...
nodeserv: 1|http://ortho.estraier.ad.jp:1978/node/child
nodeserv: 2|http://para.estraier.ad.jp:1978/node/child
nodeserv: 3|http://meta.estraier.ad.jp:1978/node/child
...

nodeservでわざわざIDをつけているのは、ノードサーバのURLが変えられるようにするためです。estwaverはどの文書をどのノードに登録したかをIDを使って記録して、文書が更新された時に古い情報を消します。したがって、IDさえ変えなければURLを変えても問題なく更新を行うことができるのです。

クローラの実行

さて、いよいよクローラを実行します。-revcontオプションは、既に取得した文書で再訪問周期になったもの(設定ファイルのrevisitで指定)を巡回した上で新たな文書の巡回を継続する指定ですが、最初からつけていても問題はありません。

estwaver crawl -revcont waver

これで巡回された文書が続々と登録されていきます。親ノードの検索用ユーザインターフェイス(http://ortho.estraier.ad.jp:1978/node/parent/search_ui)で確認してみてください。メタ検索を行うために、depthの設定は1以上にしてください。

デフォルトの設定では10000件の文書を取得した時点でクローラは停止するようになっているので、もっとたくさん集めたい場合は設定ファイルのdocnumの値を増やしてください。夜中などに定期的にクローラを走らせたい場合は、cronなどにestwaverの起動スクリプトを登録しておくとよいでしょう。

おわりに

設定が面倒で面目無いです。ほとんどの設定はノードAPIを使ったりREST風のリクエストを発行したりすれば自動化できるはずなんですが、その辺のインテグレーションは今後の課題ということで。なお、ノードAPIを使った検索アプリケーションを作ると、自前の検索エンジンを様々な用途に使えるようになると思います。ノードサーバのOpenSearch機能を利用して他の検索エンジンと連携させても面白いでしょう。

Web全体の検索エンジンはGoogleやYahooに任せておくとして、Hyper Estraierを使うと、Webの中でホットな部分に絞った検索システムを、インターネット上のユーザコミュニティが協調して構築できるようになります。estmasterのP2P機構によってPC数台でも分散処理のインデクシングができるようにし、estwaverの類似文書巡回機構によって興味のある文書を選択的に取得できるようにしているのはそのためなのです。インターネット上に設置されたノードサーバがどんどん増えて、それらが互いにリンクし合うようになれば、きっと面白い世界が見えて来るでしょう(いささか妄想気味)。