org.apache.lucene.search.Hitオブジェクトのget("title")メソッドで、ホームページのタイトルを取得しようとしたときに、データが文字化けすることがある。

どんなページのタイトルが文字化けになるかというと、

HTMLのヘッダー上で指定してある文字コードと実際のファイルの文字コードが異なるような場合。

ヘッダーの定義は、EUC-JP。

ブラウザは、Shift-JISと認識。

urlフィールドが特定の複数ドメインのもののみを取得したい

クロールしたURLが以下のようなとき

http://aaa.bb
http://ccc.dd
http://eee.ff

この2つのサイトに対してだけ検索したいときです。

http://aaa.bb
http://ccc.dd


しばらく悩んであとに、Lukeでインデックスの中身をのぞいているときに、ふと思った。。
urlフィールドを選んで、「show top terms >>」ボタンを押して、表示されるTextが単語区切りになっている・・・。
これじゃあ、Termkeino

tstampフィールドの値を"yyyy/MM/dd HH:mm:ss"形式で表示するには

tstampフィールドの値は、Lukeなどを使ってみると、"20090908080249515"のような17桁の数字になっている。

この17桁の数値は、Hitオブジェクトのgetメソッドを使って取得することができるので、これを整形できればよい。
ということで、17桁の数値のもとをたどると。。


BasicIndexingFilerクラスの100行目

doc.add(new Field("tstamp",
DateTools.timeToString(datum.getFetchTime(), DateTools.Resolution.MILLISECOND),
Field.Store.YES, Field.Index.NO));

getFetchTimeメソッドを追ってみると、

public long getFetchTime() { return fetchTime; }

fetchTimeを追ってみると、

private long fetchTime = System.currentTimeMillis();

tstampフィールドの値は、System.currentTimeMilliis()の値だということがわかる。


さて、tstampフィールドの値をHitオブジェクトのgetメソッドを通じて取得すると、String型に変換後の値が出力されるので、プログラムでtstampフィールドの値をフォーマットするには、もう少し工夫する必要があった。
つまり、String型からDate型に戻してあげる作業が。。うーん。。ほふく前進だ。

Date tstamp = DateTools.stringToDate(hit.get("tstamp"));

nutch 0.9でクロールした結果をクロールした日付順にソートしたい

nutch 0.9のbin/nutchコマンドやorg.apache.nutch.crawl.Crawlクラスのmainメソッド実行によって、作成されたDBでは、tstampフィールドに対してインデクスが付けられない。

デフォルト設定のクロールのtstampフィールド

  1. インデクスなし
  2. トーカナイズなし

フィールドでソート処理を行うためには、インデクスありでトーカナイズがされない状態である必要がある。

tstampフィールドでソートを行うために必要な状態

  1. インデクスあり
  2. トーカナイズなし

tstampフィールドの状態は、Lukeからも確認できる。

デフォルトの状態でクロールを実行してもインデクスがつかないtstampフィールドにインデックスを付けるには、

org.apache.nutch.indexer.basic.BasicIndexingFilter

を修正する必要がある。
BasicIndexingFilterクラスの100行目付近

doc.add(new Field("tstamp",
DateTools.timeToString(datum.getFetchTime(), DateTools.Resolution.MILLISECOND),
Field.Store.YES, Field.Index.NO));

となっているところを以下のように修正する

doc.add(new Field("tstamp",
DateTools.timeToString(datum.getFetchTime(), DateTools.Resolution.MILLISECOND),
Field.Store.YES, Field.Index.UN_TOKENIZED));

修正したBasicIndexingFilter.javaファイルをコンパイルして出来たBasicIndexingFilter.classクラスファイルを、含むindex-basic.jarライブラリを作りなおせばOK。

クロールを再度実行し、LUKEでインデクスの中身を見ると、tstampフィールドにインデクスが付けられているのがわかる。


プログラムからtstampフィールドでソートされたHitsオブジェクトを得るには、以下のようにtstampフィールドを指定して作成したSortオブジェクトをsearchメソッドの引数に渡せばいい。

FSDirectory indexDir = FSDirectory.getDirectory( "C:\\crawl_v09_20090908_2\\index", false );
IndexSearcher indexSearcher = new IndexSearcher( indexDir );
SortField sortField = new SortField("tstamp", SortField.STRING);
Sort sort = new Sort(sortField);
Hits hits = indexSearcher.search( new MatchAllDocsQuery(), sort );

ちなみに、以下のようにしても正しくソートされなかった。

Hits hits = indexSearcher.search( new MatchAllDocsQuery(), new Sort("tstamp", true) );

ソートを実現するにあたり、参考にさせていただいたサイトは、以下になります。
ありがとうございました!

livedoor開発日記

nutch 1.0のnutch-1.0.warアプリケーションを手動でEclipseのダイナミックウェブプロジェクトに追加する

Eclipseでnutch-1.0という名前のダイナミックウェブプロジェクトを作成する。

nutch-1.0.warファイルを適当なディレクトリに解凍する。

bin/nutchコマンドを使わずにクロールを実行する

org.apache.nutch.crawl.Crawlクラスのmainメソッドを呼び出すことで、クロールを実行することができる。

Eclipseから実行する場合、mainメソッドの引数渡すパラメータは、デバグ設定の画面から指定できる。

が、ここで問題が!

nutch 0.9までは、Crawlクラスのmainメソッド実行により作成されたデータベースに対して、Lukeなどを使って、インデクスの内容を問題なく読むことが出来たのに、nutch 1.0になってからは、Lukeを使ってインデクスの内容を読めなくなってしまった。

nutch 1.0のbinディレクトリにあるnutchコマンドを実行して作成されたデータベースは、問題なくLukeを使って内容を見ることができるので、どうゆうことなんだろう?