ブログ検索システム
Last-modified: 2012-06-09 (土) 02:03:24
Top / ブログ検索システム
※ 以下は限定公開のドキュメントが多いです。ご不便おかけします。
ブログ検索システム †
- RSSを使ったブログ・Wikiの解析 の応用編として、http://shower.human.waseda.ac.jp/~m-kouki/ 以下のコンテンツを対象とした検索エンジンを作ってみます。
- 目次
URLデータベース設計 †
- MySQL のデータベース mkouki を使います。
mysql -u root -p (パスワード) use mkouki;
RSSテーブル †
RSSのアドレスのID | RSSのアドレス |
rss_id | rss_url |
- テーブルを作る
CREATE TABLE mysearch_rss( rss_id int auto_increment, rss_url text character set utf8, index(rss_id) ); show tables;
- ここでは、カラム rss_id はオートインクリメント の設定になっています(自動的にエントリのIDをふります)。
- データを追加
INSERT INTO mysearch_rss (rss_url) VALUE('http://shower.human.waseda.ac.jp/~m-kouki/blog/atom.xml'); INSERT INTO mysearch_rss (rss_url) VALUE('http://shower.human.waseda.ac.jp/~m-kouki/pukiwiki/index.php?cmd=rss&ver=1.0'); select * from mysearch_rss limit 30;
- ここでは、手動でブログとwikiのRSSのアドレスを入れました。オートインクリメントで、rss_id は自動的に番号がつきます。
エントリーテーブル †
エントリーのID | エントリーのタイトル | エントリーのアドレス | エントリーの属性 | エントリーがインデクシング済みかどうか |
entry_id | entry_title | entry_url | entry_type | entry_indexing |
- エントリーの属性は、とりあえず「記事0、書類1、プログラム2」と決めます。
- インデクシングがまだなら0、済みなら1、とりあえず今回のシステムでは全文検索をするので、以下は全て0を代入します。
- テーブルを作る
CREATE TABLE mysearch_entry( entry_id int auto_increment, entry_title text character set utf8, entry_url text character set utf8, entry_type int, entry_indexing int, index(entry_id) );
- RSSでは取得できない、トップページ以下のURLを、とりあえず手動で追加します。 → コマンド
select entry_id, entry_title, entry_type from mysearch_entry limit 30;
クローリング †
URLデータ更新 †
- RSSのURLを参考に、各エントリーのタイトルとURLを取得して、テーブル mysearch_entry に格納します。
- プログラムの格納場所は、shower の mysearch/ とします。
- entry_url カラムの設定を「重複禁止」にしておけば、重複のチェックは不要のようです。
本文データ更新 †
- エントリーのURLを参考に、本文(とりあえずソースコード全て)を取得して、テキストファイルとして保存します。
- テキストファイル置き場を作って
mkdir /home/m-kouki/mysearch/filelog
- CrawlEntry.java を実行
chmod 755 /home/m-kouki/mysearch/filelog/*
- テキストファイル置き場を作って
検索 †
検索窓 †
- ここ のHTMLを参照。
- 検索窓に入力したクエリは mysearch.cgi が受け取り、プログラムからmysearch.sh を呼び出します。
- プログラムの格納場所は、shower の public_html/cgi-bin/ とします。
- パーミッションの設定に注意してください。
- perl から シェルスクリプトを呼び出す危険性
- 検索窓の入力内容を、そのままシェルに引数で渡すのは危険です。ここではperlプログラムがクエリファイルを書き出し、Javaプログラムが同名ファイルを読み込むようにしています(大規模な検索システムでは使えない方法です)。
- CGIではなく、Java サーブレットで実装する方法もあります(tomcat導入メモ)。試してみてください。
キーワードマッチング †
- 上のシェルスクリプトから、WordSearch.java を呼び出し、キーワードマッチングをして、SearchResult.htmlを書き出します。
- プログラムの格納場所は、shower の public_html/cgi-bin/ とします。
- パブリックな領域においたプログラムの中にパスワードを直書きするのはよくないので、public ディレクトリ以外においたパスワードファイルを参照するようにします。
- 文字化け対処として、文字コードを指定可能なファイル入出力ストリームを使います。
- ここまでの実行が終わったら、処理は再び mysearch.cgi に戻り、SearchResult.html を読み込んで、ブラウザに表示します。
課題 †
- スペースで区切った複数のクエリに対して、AND検索ができるようにしましょう。
- テキスト解析技術を使って、独自のサービスを提供してみましょう。
HTMLパース †
- HTMP Parser を参考に、パーサをインストールします。
- ここ の Downloads -> Older の htmlparser1_6_20060610.zip をダウンロードしました。解凍するときに avast! が警告するファイルは、全てその場で削除しました。
- lib フォルダ内の htmlparser.jar のみ使用します(クラスパスを通しておきます)。
CLASSPATH=$CLASSPATH:/home/m-kouki/mysearch/htmlparser.jar export CLASSPATH
- SimpleParser3.java (東京電機大 山田先生)を試してみます。
- タイトルを取得するには
java SimpleParser3 http://shower.human.waseda.ac.jp/~m-kouki/ TITLE
- 本文を取得するには
java SimpleParser3 http://shower.human.waseda.ac.jp/~m-kouki/
- 76行目 System.out.println("text: \"" + text.getText() + "\""); だけを出力するようにすればOK。
- タイトルを取得するには
URL追跡 †
- lynx を使って、トップページから順番に、URLを辿って全てのコンテンツを取得してみます。
lynx †
- lynx でウェブページにアクセスするには、
lynx -dump http://shower.human.waseda.ac.jp/~m-kouki/
. . k-lab_wiki [23] 兇wiki _________________________________________________________________ Copyright(C) [24]MIYAZAWA Kouki All Rights Reserved. 繚 1. http://shower.human.waseda.ac.jp/~m-kouki/blog/ 2. http://shower.human.waseda.ac.jp/~m-kouki/pukiwiki/index.php?FrontPage 3. http://shower.human.waseda.ac.jp/~m-kouki/reference/index.html 4. http://shower.human.waseda.ac.jp/~m-kouki/kensyu/index.html 5. http://shower.human.waseda.ac.jp/~m-kouki/collaboration/index.html . .
- 指定したウェブサイトの文字コードが、lynx の設定ファイルの文字コード と異なる場合、本文が文字化けします。
- とりあえず今回は、最後のリンク情報が取得できればいいので、lynx の設定ファイルは変更しません。
- Basic認証付きのページにアクセスするには、
lynx -dump -auth=(ID):(パスワード) (URL)
- lynx に xml ファイルのアドレス(RSSなど)を指定すると、正しくURLを取得することができません。以下では、取得した URL を再度 lynx にかけ、出力が得られるかどうかで、URL が正しいかどうかを判定しています。
java から呼び出す †
- javafaq 外部コマンド呼出し を参考にして、
- CrawlLynxTest1.java
import java.io.*; public class CrawlLynxTest1 { public static void main(String[] args) { try { Process process = Runtime.getRuntime().exec ("lynx -dump http://shower.human.waseda.ac.jp/~m-kouki/"); InputStream is = process.getInputStream(); BufferedReader br = new BufferedReader(new InputStreamReader(is)); String line; while ((line = br.readLine()) != null) { System.out.println(line); } is.close(); br.close(); } catch (Exception err) { System.out.println(err); } } }
- CrawlLynxTest1.java
実装 †
- lynx で指定したページのリンクを取得 → 取得したURLが存在するかどうかを確認 → HTML パーサでリンク先のタイトルを取得 → リンク先のファイルの拡張子から属性を判定 → データベースに格納 の流れを再帰的に繰り返します。
- トップページのURLを引数として、各エントリーのタイトル(ファイル名)とURLを取得して、テーブル mysearch_entry に格納します。
- クラスパスを通して、CrawlLynx.java を実行
CLASSPATH=$CLASSPATH:/home/m-kouki/mysearch/ mysql-connector-java-5.1.6/mysql-connector-java-5.1.6-bin.jar export CLASSPATH java CrawlLynx m-kouki http://shower.human.waseda.ac.jp/~m-kouki/ 10
- 引数の意味 : http://shower.human.waseda.ac.jp/~m-kouki/ から検索開始、m-kouki の含まれるアドレスのみ、第10階層までクロール
- CrawlRSS.java の実行後に行ってください。CrawlRSS.java ですでに取得済みの、ブログとwikiの記事は、重複URLとなり格納されません。
- タイトルの取得には、SimpleParser3.java を外部クラスから実行できるようにした、SimpleParser3_2.java を使用しています。
- エントリーの属性は、「書類(txt)1、プログラム(java, m, perl)2、PDF 3、 WORD文書 4、動画(wmv) 5、パワーポイント 6、圧縮ファイル(zip, lzh) 7、その他 0」と決めます。
- プログラムの格納場所は、shower の mysearch/ とします。
- クラスパスを通して、CrawlLynx.java を実行
改良すべき点 †
- lynx の代わりに HTML Parser で A タグのテキストと URL を解析すれば、リンク先のファイルが HTML でなくても正確なタイトルを取得できそうです。
- 時間がかかりすぎる。一度検索したリンクは検索しないなど、ループを防ぐ工夫が要るかも。
リンク切れを削除 †
- mysearch_entry テーブルの entry_url カラムを順番に取得して、リンク先が生きているかを確認(lynx が null もしくは Not Found を返さないことを確認) します。
- ついでに、上の追跡検索でヒットしてしまう、検索対象にしたくないページ(wikiのバックアップやBlogのインデックス等)を削除します。
- DeleteLinks.java を実行
- 上のプログラム中で読み込む deletelinks_url.txt と deletelinks_title.txt は、削除したい URL や タイトルの一部を列挙したファイルです。
インデックスをつける †
HTML以外のファイルを取得する †
- CrawlEntry.java の改良案です(CrawlEntry2.java)。
- 以下は HTMLパーサでは「WARNING: URL ~~ does not contain text」エラーが出ます。そのため、これまでの手法では内容をログファイルにできないため、検索することができません。
PDFファイルを取得 †
- PDFビューア
- エントリーの属性が「3」だったときは、wget でダウンロード → Xpdf でPDFファイルをテキストファイルに変換
PPTとWORDファイルを取得 †
ZIPファイルを取得 †
検索 †
- WordSearch.java の改良案です。
検索窓でファイルの属性を指定する †
表記ゆれ対処 †
- 大文字・小文字など。
定期クロール †
- RSS検索
cd /home/m-kouki/mysearch/ CLASSPATH=$CLASSPATH:informa.jar CLASSPATH=$CLASSPATH:lib/commons-logging.jar CLASSPATH=$CLASSPATH:lib/jdom.jar CLASSPATH=$CLASSPATH:htmlparser.jar CLASSPATH=$CLASSPATH:mysql-connector-java-5.1.6/mysql-connector-java-5.1.6-bin.jar export CLASSPATH java CrawlRSS
- 追跡検索
java CrawlLynx m-kouki http://shower.human.waseda.ac.jp/~m-kouki/ 3 java CrawlLynx m-kouki http://shower.human.waseda.ac.jp/~m-kouki/blog/archives.html 2
- 削除とファイルログ保存
java DeleteLinks rm /home/m-kouki/mysearch/filelog/* java CrawlEntry2 rm *.pdf* chmod 755 /home/m-kouki/mysearch/filelog/*
cronで自動化 †
- 参考
- cron コマンドに関して [#c2aab7e5]
- crontabで定期的自動実行
- /etc/cron は、shinzan には存在しない。
- ユーザ m-kouki のスケジュールを変更するには
$ crontab -u m-kouki -e
- エディタで、
# m h dom mon dow command * * 14 6 6 date > date.txt
などとして、Ctrl+O → 「File Name to Write: 」はそのままで、Enter → Ctrl+X で終了する。
- エディタで、