トップ   編集 差分 バックアップ 添付 複製 名前変更 リロード   新規 一覧 単語検索   ヘルプ   最終更新のRSS

RSSを使ったブログ・Wikiの解析 の変更点

Top / RSSを使ったブログ・Wikiの解析

#access
#analog

※以下は内部限定公開のドキュメントが多いです。ご不便おかけします。

*RSSを使ったブログ・Wikiの解析(ブログ検索システムの開発) [#r495c2de]

***目次 [#da57fbe5]

#contents


***目的 [#ac36f0dd]
-ブログやWikiの更新情報、記事テキストの本文、リンクなどを取得するJavaプログラムを作りましょう。
-[[MySQLデータベース:http://www.atmarkit.co.jp/flinux/index/indexfiles/mysqlindex.html]] にデータを格納する方法、Java プログラムからMySQL にアクセスする方法について理解しましょう。
-ブログの記事テキストを、さまざまな自然言語処理の技術を使って解析してみましょう。
-Webアプリケーション(検索エンジン)として実装しましょう。

**ブログの情報を取得する [#id73b930]
-ここでは、菊池研個人ブログのテキストを収集して、解析してみましょう。

***RSSを取得する [#befe7384]
-参考
--[[RSS:http://ja.wikipedia.org/wiki/RSS]] 
--[[Blog情報一覧(菊池研wiki):http://shinzan.human.waseda.ac.jp/wiki/index.php?Blog%BE%F0%CA%F3%B0%EC%CD%F7]]
--[[Six Apart - フィードとは?:http://www.sixapart.jp/about/feeds/]]

-菊池研のブログ(Movable Type 4.0)のRSSフィードを見るには、ブログのトップページにある「このブログを購読」をクリック

&ref(http://shower.human.waseda.ac.jp/~m-kouki/images/blogsearch1.png);~

-[[こんな感じ:http://shower.human.waseda.ac.jp/~m-kouki/blog/atom.xml]]
--<entry> ~ </entry> が一つのエントリー
---<title> ~ </title> がタイトルで、
---<link ... href= " ~ " /> がURLで、
---<![CDATA[ ~ ]]> が本文(ひとつのエントリーに複数存在する場合あり)

-RSSを取得する
--[[JavaでHello World URL編:http://www.hellohiro.com/url.htm]] を参考に
--TestSearch1.java
#geshi(java){{
 import java.net.*;
 import java.io.*;
 public class TestSearch1 {
   public static void main(String[] args) {
     そのままなので省略
   }
 }
}}

---ここではとりあえず、[[宮澤のブログ:http://shower.human.waseda.ac.jp/~m-kouki/blog/]] のRSSを取得してみます。URL部に http://shower.human.waseda.ac.jp/~m-kouki/blog/atom.xml を直接指定しましょう。
---文字化け対処として、インプットストリームの部分を以下に差し替えます。
#geshi(java){{
 // 入力ストリームを生成
 BufferedReader in = new BufferedReader(
                           new InputStreamReader(
                           helloURL.openStream(), "UTF8"));
}}

---プログラムを実行して、RSSのXML文書が表示されることを確認してください。

***RSSパーサを使って、RSSを解析する [#r6e62c03]
-上で確認してもらったように、RSSのXML文書の中には、ブログに関するさまざまな情報がタグ付きで入っています。このタグを読み込んで、目的の部分だけを取り出すプログラムパッケージが RSSパーサ です。

-ここでは、Java用XMLパーサ、[[Informa:http://informa.sourceforge.net/]] を使います。
--別の方法として、perl用のRSSパーサ [[XML::FeedPP:http://www.kawa.net/works/perl/feedpp/feedpp.html]] を使うやり方は、[[こちら:http://shower.human.waseda.ac.jp/~m-kouki/pukiwiki/index.php?Web%E6%83%85%E5%A0%B1%E8%A7%A3%E6%9E%90%EF%BC%88%E6%97%A7%EF%BC%89#r6e62c03]] にまとめてあります(一部のブログでエラーが出る可能性があります)。

-Informa をダウンロード
--[[ここ:http://informa.sourceforge.net/]] から Downloads > Download > informa-0.7.0-alpha2-with-dependencies.zip を選んで、解凍してください(2009/02/16現在)。
--解凍してできる informa-0.7.0-alpha2 直下の informa.jar と、lib ディレクトリの中身を全て、プログラムを実行するディレクトリの中に移します。
---下記のプログラムで使うのは、特に informa.jar lib/commons-logging.jar lib/jdom.jar の3つです。

-Informa.jar を置いたディレクトリの中に、以下のJavaプログラム TestSearch2.java を作ります。
--参考 : [[Informa で RSS フィードを変更してみる:http://blogs.sun.com/katakai/entry/informa_to_get_rdf]]
--'''[[TestSearch2.java:http://shower.human.waseda.ac.jp/~m-kouki/pg/TestSearch2.java.txt]]'''

-コンパイルと実行
--上記のプログラムのある場所(ターミナルもしくはLinuxサーバ)で、Informa にクラスパスを通して、コンパイルします。
 $ CLASSPATH=$CLASSPATH:informa.jar
 $ CLASSPATH=$CLASSPATH:./lib/commons-logging.jar
 $ CLASSPATH=$CLASSPATH:./lib/jdom.jar
 $ export CLASSPATH
 $ javac TestSearch2.java
---参考 : [[パスとクラスパス:http://shower.human.waseda.ac.jp/~m-kouki/pukiwiki/index.php?Linux%E3%82%B5%E3%83%BC%E3%83%90%E9%96%A2%E4%BF%82#r00288c9]]
---毎回クラスパスを宣言しないですむように、bashの設定ファイルを変更する方法は、[[Blog検索エンジンby北村:http://shinzan.human.waseda.ac.jp/wiki/index.php?Blog%B8%A1%BA%F7%A5%A8%A5%F3%A5%B8%A5%F3#l4dee892]] に書かれています。
--実行します。
 $ java TestSearch2 
---TestSearch1.java よりも詳しい情報を取り出すことができました。
---最新記事のURL一覧が、[[testSearch2_url.txt:http://shower.human.waseda.ac.jp/~m-kouki/websearch/testSearch2_url.txt]] に書き出されました(実行するたびに追記されていくことに注意)。

***HTMLパーサを使って、各記事を解析する [#r6e62c03]
-上で実行したように、TestSearch2.java によって、[[宮澤のブログ:http://shower.human.waseda.ac.jp/~m-kouki/blog/]] の最新記事のタイトル、URL、HTMLが取得できました。
-続いて、記事のHTMLを解析して、記事本文やその他の情報を取得しましょう。
-HTMLパーサをインストールします。
--参考:[[HTMP Parser:http://www.mlab.im.dendai.ac.jp/~yamada/ir/HTMLParser/]]
--[[ここ:http://htmlparser.sourceforge.net/]] から Downloads > Older > htmlparser1_6_20060610.zip を選んで、解凍してください(2009/02/16現在)。
---ウイルス対策ソフト avast! を使っている場合、インストール中に警告が出ます。該当ファイルを全てその場で削除しても問題なく動きました。
--lib フォルダ内の htmlparser.jar のみ使用します(クラスパスを通しておきます)。
 CLASSPATH=$CLASSPATH:/home/m-kouki/mysearch/htmlparser.jar
 export CLASSPATH
-HTMLを解析する
--[[HTML Parser:http://www.mlab.im.dendai.ac.jp/~yamada/ir/HTMLParser/]]の[[SimpleParser3.java:http://www.mlab.im.dendai.ac.jp/~yamada/ir/HTMLParser/SimpleParser3.html]] を参考にします。
-'''[[TestSearch3.java:http://shower.human.waseda.ac.jp/~m-kouki/pg/TestSearch3.java.txt]]''' を実行しましょう。
--上で作った testSearch2_url.txt を読み込み、書かれたURLの記事中に出現するリンクと本文を取得して表示します。
--このプログラムのディレクトリ直下に testSearch3 ディレクトリを作り、各記事の本文を格納します([[例:http://shower.human.waseda.ac.jp/~m-kouki/websearch/testSearch3_0.txt]])。
--【注意】改行記号、スペース、パーサで取り除けなかったタグが残ります。そのため、[[文字列の一部を削除する - Java(SE) API 逆引き辞典:http://always-pg.com/java/j2se_rd/string/buffer_delete.html]] を参考に、RemoveStrings、RemoveTags メソッドを使って後処理をしています。

***上記処理の自動化 [#o0e65126]
-''&color(red){発展課題1};'' TestSearch2.java ~ TestSearch3.java を改造して、RSSのページのURL と、出力先のディレクトリ名を引数で与えたら、自動的にRSSを解析して各記事の本文を出力ディレクトリ内に書き出すプログラム TestSearchEx.java を作ってください。
--例えば、http://shower.human.waseda.ac.jp/~m-kouki/blog/atom.xml のRSSの解析結果を、m-kouki ディレクトリに保存したいとき、以下で実行できるようにしましょう。
 $ java TestSearchEx http://shower.human.waseda.ac.jp/~m-kouki/blog/atom.xml m-kouki
--'''[[解答例:http://shower.human.waseda.ac.jp/~m-kouki/pg/TestSearchEx.java.txt]]'''
-''&color(red){発展課題2};'' 研究室の各人のブログのRSSのURLを指定して、それぞれの記事を取得し、本文を別々のディレクトリに保存してみましょう。
--パスワード付きのURLについて、[[URLStreamHandler (Java 2 Platform SE 5.0):http://java.sun.com/j2se/1.5.0/ja/docs/ja/api/java/net/URLStreamHandler.html]] を参考にユーザ情報を指定することで対処できそうです。
--難しいようなら、手動でパスワードを入力して XML ファイルをダウンロードして、パソコンに保存したXMLファイルのパスを引数で与えてもいいでしょう。


**MySQLデータベース にデータを格納する [#j4bb0924]
-ここまでのプログラムでは、取得したブログ情報を表示したり、テキストで書き出したりしました。ここでは、データベースアプリケーション [[MySQL:http://www.atmarkit.co.jp/flinux/index/indexfiles/mysqlindex.html]] を使って、取得した情報を管理したり、Java でデータベースにアクセスしたりする方法について説明します。

***データベースを設計する [#s7199b11]
-MySQL は[[リレーショナルデータベース:http://ash.jp/db/rdb.htm]] ですので、データは表(テーブル)と項目(カラム)によって管理されます。
-ここでは、ユーザ名「mkouki」、データベース名「mkouki_TestBlogSearch」の中に、RSSのデータを格納するテーブル mysearch_rss と、各記事のデータを管理するテーブル mysearch_entry を作ることにします。

-RSSテーブル mysearch_rss の構造
|BGCOLOR(white):RSSのアドレスのID |BGCOLOR(white):RSSのアドレス |
|rss_id|rss_url|

-エントリーテーブル mysearch_entry の構造
|BGCOLOR(white):エントリーのID |BGCOLOR(white):エントリーのタイトル |BGCOLOR(white):エントリーのアドレス |BGCOLOR(white):エントリーの属性 |BGCOLOR(white):エントリーがインデクシング済みかどうか |
|entry_id|entry_title|entry_url|entry_type|entry_indexing|
--各エントリーの本文は、URLからその都度取りに行く仕様にしました。大規模な検索エンジンの場合、この方法は時間がかかりすぎるため、現実的ではありません。
--エントリーの属性は、とりあえず「記事0、書類1、プログラム2」と決めます。
--インデクシング(記事テキストから重要な情報のみを抽出して圧縮すること)がまだなら0、済みなら1、と決めます。

***データベースを作る [#x27e9680]
-以下は shower もしくは shinzan で行ってください。
-&color(red){''【注意】'' 初めて使う場合は、[[MySQLのユーザー設定:http://shower.human.waseda.ac.jp/~m-kouki/pukiwiki/index.php?SQL#vd1d5f21]] が必要です。[[宮澤までメール:m-kouki@moegi.waseda.jp]] をください。その際、サーバー名(shower か shinzan)、データベース名、ユーザー名、希望するパスワード を教えてください。};
--自分で設定することもできます。[[MySQLの設定:http://shinzan.human.waseda.ac.jp/wiki/index.php?%A5%D6%A5%ED%A5%B0%A4%CE%BA%EE%A4%EA%CA%FD#u291f6a7]] の手順に従ってください。
-はじめに、MySQLを起動します。
 $ mysql -u ユーザー名 -p
 (希望したパスワード)
-MySQLの画面になりますので、以下を入力します。
 use (希望したデータベース名);  # データベースの使用宣言
--「Database changed」と出たら成功です。
-テーブルを作成します。
 CREATE TABLE mysearch_rss( rss_id int auto_increment, 
  rss_url text character set utf8, index(rss_id) );
 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) );
 show tables;
--以下のように出たら、成功です。
 +---------------------------------+
 | Tables_in_mkouki_TestBlogSearch |
 +---------------------------------+
 | mysearch_entry                  |
 | mysearch_rss                    |
 +---------------------------------+
 2 rows in set (0.00 sec)
---rss_id カラム、rss_url カラムを持つテーブル mysearch_rss ができました。また、entry_id カラム、entry_title カラム、entry_url カラム、entry_type カラム、entry_indexing カラムを持つテーブル mysearch_entry ができました。
---ここでは、カラム rss_id と entry_id は[[オートインクリメント:http://www.dbonline.jp/mysql/table/index6.html]] の設定になっています(自動的にID番号をふります)。

--mysearch_rss テーブルにデータを追加してみましょう。
 INSERT INTO mysearch_rss(rss_url) VALUE('http://shower.human.waseda.ac.jp/~m-kouki/blog/atom.xml');
-テーブルの中身を確認するには
 SELECT * from mysearch_rss;
--以下のように出たら、成功です。
 +--------+---------------------------------------------------------+
 | rss_id | rss_url                                                 |
 +--------+---------------------------------------------------------+
 |      1 | http://shower.human.waseda.ac.jp/~m-kouki/blog/atom.xml |
 +--------+---------------------------------------------------------+
 1 row in set (0.00 sec)

--mysearch_entry テーブルにデータを追加してみましょう。
 INSERT INTO mysearch_entry(entry_title, entry_url, entry_type, entry_indexing)
  VALUE('Miyazawa Kouki',
  'http://shower.human.waseda.ac.jp/~m-kouki/',
  0, 0);

--特定のカラムの中身を確認するには
 SELECT rss_url from mysearch_rss limit 10;
 # mysearch_rss テーブルの rss_url カラムの中身を 10個だけ表示(まだ1つしか表示されません)
--ついでに、テーブルを消すには、
 DROP table (消したいテーブルの名前)

***Javaからデータベースにデータを入れる [#m03d723f]
-続いて、Java から MySQLを呼び出します。
-[[JavaでHello World JDBC(MySQL)編:http://www.hellohiro.com/jdbcmysql.htm]] を参考に、JDBC ドライバをダウンロードします。
--[[MySQL Downloads:http://dev.mysql.com/downloads/]] から Connectors > Connector/J > Download Connector/J 5.1 > Source and Binaries (zip) > Pick a mirror > New Users > Proceed > (適当に情報を入力) > submit form > 日本のHTTP を選んで、mysql-connector-java-5.1.7.zip をダウンロードして解凍してください(2009/02/16現在)。
--クラスパスを通しておきます。
 CLASSPATH=$CLASSPATH:mysql-connector-java-5.1.7/mysql-connector-java-5.1.7-bin.jar
 export CLASSPATH

-テストプログラムを実行してみます。上記サイトと [[MySQL ドライバー:http://www.nextindex.net/java/JDBC/mmMySQL.html]]、[[レコード更新:http://homepage2.nifty.com/sak/w_sak3/doc/sysbrd/mysql_05.htm]] を参考に... 
-'''[[TestMySQL1.java:http://shower.human.waseda.ac.jp/~m-kouki/pg/TestMySQL1.java.txt]]'''
--ユーザ名、データベース名、パスワードを書き換えて実行してください。
---&color(red){パスワードをソース中に直書きするため、扱いには十分注意してください!};
--実行は以下のようにします。
 java TestMySQL1 test_title test_url 0 0
---上手くいけば、下記のように、mysearch_entryテーブルにデータを追記し、その結果を出力します。
 INPUT : タイトル  URL  属性  インデックス  ← 引数で指定したデータ
 INSERT INTO mysearch_entry
  (entry_title, entry_url, entry_type, entry_indexing) VALUE('test_title', 'test_url', '0', '0')
 ID      タイトル  URL  属性  インデックス ← データベースに格納されたデータ

-''&color(red){発展課題3};'' RSSフィードの URL から、各記事のタイトル・URLを取得して、データベースに格納してみましょう。可能であれば、mysearch_entry テーブルに各記事の本文を格納するカラムを追加して、本文もデータベースに格納するようにしましょう。

***Javaでデータベースからデータを取り出す [#ub8251d0]
-'''[[TestMySQL2.java:http://shower.human.waseda.ac.jp/~m-kouki/pg/TestMySQL2.java.txt]]'''
--実行は以下のようにします。
 java TestMySQL2
---mysearch_entryテーブルに格納されている entry_id と entry_url の一覧を表示します。


**実装 [#f1948460]
-応用編として、&pgid(,ブログ検索システム); に、宮澤のブログ・wikiのRSSから本文を取得し、検索するシステム([[ここ:http://shower.human.waseda.ac.jp/~m-kouki/]]の上端にあるやつです)の作り方をメモしておきました。
-ぜひ、オリジナルのシステムに挑戦してみましょう。