Y's note

Web技術・プロダクトマネジメント・そして経営について

本ブログの更新を停止しており、今後は下記Noteに記載していきます。
https://note.com/yutakikuchi/

検索Crawlerを作る

Solr in Action

Solr in Action

Nutch + Solr + Hbase + Zookeeper

Nutchで特定のWebPageをCrawlingしてSolrのIndexを作ろうとした時にかなり嵌ってしまったので作業のメモを記録しておきます。(※タイトルに語弊があるようですが、検索Crawler自体を作るという話ではありません。)特にNuth/Hbase間のVersion依存があるので、installしてみたけど動かなかったという人の参考になればと思います。Webを色々と探してみるとNutch2.2.1Hbase0.90.Xを組み合わせると良いようです。僕が試してみた環境は以下のものです。因にZookeeperは個別にinstallする必要は無いようです、Hbaseを起動するとZookeeperも実行されます。

  • OS : CentOS 6.4
  • Java : 1.7.0_51
  • Nutch : 2.2.1
  • Solr : 4.7.0
  • Hbase : 0.90.6
  • Zookeeper : 3.4.6

またNutchのTutorialに関しても注意が必要です。Webで紹介されているものは1.X系のものが多く、Crawlingのコマンドも掲載されているものをそのまま実行するとdeprecatedされていて動かなかったりします。NutchのVersionを確認して必要なTutorialを参照するようにしましょう。 特に一番したのリンクのCommandLineOptionsに記載されているVersion毎の×印を参考にすると良いでしょう。

Setup

基本的にはどれもWebから圧縮ファイルをdownloadして解凍し、設定ファイルの変更と起動コマンドの実行により動きます。ここではJavaは既に設定されているものとして話を進めます。

HBase

今回のHBaseの目的はCrawlingした結果を一時的に保存する為のDBになります。以下は設定ファイルの更新とHBase起動と接続してみてテスト用のTABLEを作ってみます。注意したい内容としてはHBaseの起動の前にZookeeperを先に起動していると既にPortを使用している等のErrorが出てしまいます。今回はここに数時間嵌って作業が進みませんでした。Zookeeperのプロセスを一度停止した後にHBaseを起動するか、HBaseのZookeeperのportを別に立てても良いかもしれません。Errorの内容は一番下に記載しておきます。

$ wget http://archive.apache.org/dist/hbase/hbase-0.90.6/hbase-0.90.6.tar.gz
$ tar -xzf hbase-0.90.6.tar.gz
$ cd hbase-0.90.6
$ vi conf/hbase-site.xml

<configuration>
  <property>
    <name>hbase.rootdir</name>
    <value>file:///<yourpath>/hbase/hbase-0.90.6</value>
  </property>
  <property>
    <name>hbase.zookeeper.property.dataDir</name>
    <value>/var/lib/zookeeper</value>
  </property>
  <property>
    <name>hbase.zookeeper.quorum</name>
    <value>localhost</value>
  </property>
  <property>
    <name>hbase.zookeeper.property.clientPort</name>
    <value>2181</value>
   </property>
</configuration>

$ sudo mkdir -p /var/lib/zookeeper
$ bin/start-hbase.sh

$ bin/hbase shell
$ hbase(main):001:0> create "hoge", "foo"
0 row(s) in 0.9400 seconds

$ hbase(main):002:0> list
TABLE
hoge
1 row(s) in 0.0310 seconds
$ hbase(main):001:0> create "hoge", "foo"
ERROR: org.apache.hadoop.hbase.MasterNotRunningException: null

$ vi hbase-0.90.6/logs/<your-path>.log
Could not start ZK at requested port of 2181.  ZK was started at port: 2182.  Aborting as clients (e.g. shell) will not be able to find this ZK quorum.
Nutch

antによるBuildが必要ですが、作業内容はさほど多く無いので簡単に設定できると思います。Build完了後に実際にNutchを動かしてみて、Crawling結果をHBaseに格納してみます。成功するとwebpageというTABLEがHBase上に作成されているので、scan "webpage"とコマンドを実行すると格納されたデータが見れると思います。このHBaseに格納されたデータをSolrのIndexに入れて行きます。

$ wget http://ftp.kddilabs.jp/infosystems/apache/nutch/2.2.1/apache-nutch-2.2.1-src.tar.gz
$ tar -xzf apache-nutch-2.2.1-src.tar.gz
$ cd apache-nutch-2.2.1
$ vi conf/nutch-site.xml

<configuration>
  <property>
    <name>http.agent.name</name>
    <value>Nutch-bot</value>
  </property>
  <property>
    <name>storage.data.store.class</name>
    <value>org.apache.gora.hbase.store.HBaseStore</value>
    <description>Default class for storing data</description>
  </property>
</configuration>

$ vi conf/gora.properties

gora.datastore.default=org.apache.gora.hbase.store.HBaseStore         //comment-in
#gora.datastore.default=org.apache.gora.mock.store.MockDataStore  //comment-out
gora.datastore.autocreateschema=true                                                //comment-in

$ vi ivy/ivy.xml

<dependency org="org.apache.gora" name="gora-hbase" rev="0.3" conf="*->default" />  //comment-in

$ ant runtime
Buildfile: build.xml
Trying to override old definition of task javac
  [taskdef] Could not load definitions from resource org/sonar/ant/antlib.xml. It could not be found.

ivy-probe-antlib:

()

BUILD SUCCESSFUL
Total time: 20 seconds

$ cd runtime/local/
$ mkdir urls
$ vi urls/seeds.txt

http://yut.hatenablog.com

$ bin/nutch inject urls
$ bin/nutch generate -topN 1
$ bin/nutch fetch -all
$ bin/nutch parse -all
$ bin/nutch updatedb

$ hbase(main):003:0> list
TABLE
hoge
webpage

$ hbase(main):004:0> scan "webpage"

()

org.apache.httpd:http/docs column=mtdt:_csh_, timestamp=1411442301111, value=<@\xC0\xC1
 /trunk/mod/mod_usertrack.h
 tml
 org.apache.httpd:http/docs column=s:s, timestamp=1411442301111, value=<@\xC0\xC1
 /trunk/mod/mod_usertrack.h
 tml
85 row(s) in 4.1510 seconds
Solr

Solrの圧縮ファイルを取得し、既に含まれているexampleのstart.jarを実行するだけです。ただしCrawlingした結果を格納するにはconf/schema.xmlを内容に合せて修正しなければならないので、nutchのhomeからschema-solr4.xmlをsolrのディレクトリにschema.xmlをcopyし、という行を追加します。(この行の追加に何があるのかはまだ良く分かっていません。) 準備が整った段階でHBaseに格納されたデータをSolrのIndexに反映し、結果が取得できる事を確認します。

$ wget "ftp://ftp.riken.jp/net/apache/lucene/solr/4.7.0/solr-4.7.0.tgz"
$ tar xf solr-4.7.0.tgz
$ cp ${NUTCH_RUNTIME_HOME}/conf/schema-solr4.xml ${APACHE_SOLR_HOME}/example/solr/collection1/conf/schema.xml
$ vi ${APACHE_SOLR_HOME}/example/solr/collection1/conf/schema.xml
$ cd ${APACHE_SOLR_HOME}/example/
$ java -jar start.jar
$ cd ${NUTCH_RUNTIME_HOME}/runtime/local/
$ bin/nutch solrindex http://localhost:8983/solr/ -all
$ curl "http://localhost:8983/solr/collection1/select?q=*%3A*&wt=json&indent=true"

{
  "responseHeader":{
    "status":0,
    "QTime":0,
    "params":{
      "indent":"true",
      "q":"*:*",
      "wt":"json"}},
  "response":{"numFound":1,"start":0,"docs":[
      {
        "content":"Web就活日記 スマートフォン用の表示で見る スターをつけました Web就活日記 愛と夢と人生について書きます......
        "id":"com.hatenablog.yut:http/",
        "title":"Web就活日記",
        "boost":1.0058652,
        "digest":"9316b0293d5432cf33b38195e038a9df",
        "tstamp":"2014-10-23T03:17:50.204Z",
        "url":"http://yut.hatenablog.com/",
        "_version_":1480021283528769536}]
  }}

Nutchのその他Option

Index化するURLを増やしたいとき

bin/nutch generate -topN n のnの回数を増やすと良いようです。1.X系の場合はdepthというパラメータで制御するようだったんですが、2.X系は無いようです。topNの値を増やすとgenerate,fetch,parseの処理が重たくなるので気をつけましょう。

$ bin/nutch generate -topN 100
$ bin/nutch fetch -all
$ bin/nutch parse -all
特定のWebPage内だけをCrawlingしたい場合

conf/nutch-site.xmlに以下の内容を記載すれば外部PageをCrawlingの対象外にします。

$ vi conf/nutch-site.xml

  <property>
    <name>db.ignore.external.links</name>
    <value>true</value>
  </property>