RSSを読み込む:rubygems:simple-rss
結局,夏期休暇の課題をメーラでやるのは間に合いそうにないんで,RSSリーダーをでっち上げて提出したのですが,そのRSSフィードをパースする部分はrexml/documentでもってやったわけです.
しかしながら先人ってのは色んな分野に居るもので,gemを検索して見ると出てきたよ!
- simple-rss (1.1, 1.0.0)
A simple, flexible, extensible, and liberal RSS and Atom reader for Ruby. It is designed to be backwards compatible with the standard RSS parser, but will never do RSS generation.
早速試してみるぞ.長くなるので『続きを読む』で色々する.
ソースをチラッと読む
なんかスゲー短い.simple-rss.rbだけで,他にライブラリやモジュール的なものは一切無し.たったの131行で,rexmlとか使うのかなーとか思ったら,requireしてるのはcgiとtimeだけ.何故にcgi.コメントもなんだかお粗末,というかほっとんど無く,initializeを見てみると
def initialize(source) @source = source.respond_to?(:read) ? source.read : source.to_s @items = Array.new parse end
パッと見た感じではsourceって何!ってなる.…ファイル?あ,あれか.xmlのファイルもしくはドキュメントそのものだな!
respond_to?ってのは初めて見るんだけど,これはそのオブジェクトに引数で渡された名前(でいいの?)のメソッドがあるか調べるヤツ.
> "hoge".respond_to?(:+) => true > "hoge".respond_to?(:-) => false
ファイルならreadってメソッドは確かにあるし,ファイルじゃなかったらとりあえず文字列化しちまえって感じですね.ということで,このsourceにはFileかXMLのなんかオブジェクトを持ってきてやらないとだめと.
とりあえず何か作る
とりあえず何か作って使い方のお勉強.簡単なもの.
# simrss.rb require 'net/http' require 'uri' require 'rubygems' require 'simple-rss' url = ARGV.shift if url uri = URI.parse(url) else puts "usage:" puts "$ ruby simrss.rb [feed url]" exit end body = nil begin Net::HTTP.start(uri.host) do |http| path = uri.path unless uri.query.nil? path += '?' + url.query end req = Net::HTTP::Get.new(path) res = http.request(req) body = res.body.to_s end rescue SocketError puts "#{url}?そんなアドレス無いです." exit end rss = SimpleRSS.new(body) puts rss.title puts rss.description puts rss.link rss.items.each_with_index do |item, i| puts "-" * 30 puts item.title puts item.description break if i >= 2 end
とりあえず,url指定してそのフィードからxml落として色々表示って感じでやってみた.実行して見るとこんな感じです.RSSフィードは,phpspot開発日誌さんのを*1.
$ ruby simrss.rb 'http://phpspot.org/blog/index.rdf' phpspot開発日誌 PHPライブラリ紹介と最近のWEB技術情報をお届け http://phpspot.org/blog/ ------------------------------ Yahoo! UI Library を使ったページ送りが可能なグリッドコンポーネント YUI Grid Sample This is a sample of using the YUI Grid creat... ------------------------------ MeCabを使った形態素解析をAPI経由で簡単に使える『MECAPI』 MECAPI Use "MeCab", the Japanese morphological ana... ------------------------------ PHPで画像に使われている色を簡単に抽出する方法 Color Extract クラス PHPで画像に使われている色を抽出する方法。 Flickr にあるような画像の色検索な...
う〜ん,手軽.
簡単に使い方を纏める
習うより慣れろ,変に勘ぐるよりも,まずコードを書いてみたらフィーリングでできたのですが*2,軽く使い方を纏めておきます.
new
新しくインスタンスを作成するときは,先述した通り,newにxmlのファイルかhttpのリクエストか何かで取ってきたレスポンスのbodyを渡してやればオッケー.
rss = SimpleRSS.new(File.open("file.xml")) # もしくは # rss = SimpleRSS.new(File.open(response.body)) などなど
フィードの情報を見る
SimpleRSSクラスのアクセサには,
- items(entriesにエイリアスが貼られてる)
- source
の2つがあります.2つ目のsourceは,読み込んだxmlがStringでそのまんま入ってます.使い道は殆ど無いかな?1つ目のitemsは,行ってみればフィードのエントリーで,配列になっています.なので上のスクリプトではeachでグルグル回して処理できるわけです.
item = simplerss.items[1] puts item.title
とかでそのエントリーのタイトルを表示してくれるのですが,ご存知の方もおられると思いますが,XML的にはRDFでいうところのdescriptionがAtom feedではsummaryになっていまして*3,Atom feedを読み込んでitem.descriptionとしてもnilが返ってくるだけだったりします.この辺りはチョット不便かな.
もっと厄介なのは,このRSS"自体"の要素.titleやdescription(上のスクリプトの,rss.title,rss.description)みたいな.
たとえば,RDFならdescriptionで良いものがAtom feedならtaglineって名前になってて,しかもrss.descriptionってやっても(itemならnilが返ってくるところだけど)NoMethodErrorが発生する.で,試しにtaglineを呼んでみてもNoMmethodError.どうなってんだ?
さらばNoMethodError?
そこで,gemのsimple-rss.rbをちょこっと弄ってみる.
@@feed_tags = [ :id, :title, :subtitle, :link, :description, :tagline, # :taglineを追加
こうすると,NoMethodErrorは解消できた.やったね!こんな感じに自分独自でタグを増やしてカスタマイズするってのもアリですね.拡張性があって,良いgemです.
全体的に見て
スゴく便利なのは便利.ただ,読み込んだフィードがRSS 1.0なのかRSS 2.0なのか,はたまたAtom feedなのかその他諸々のRSS 0.9xなのか,わからないのが悔しい.
試しに,feed_tagsにrdf,rss,feedを追加してみたんだけど,パースにスゴい時間食ってしまったみたいで,良い解決策とは言えない.なんで3つ増やしただけで恐ろしく遅くなったかはわかんないけれど.
そこさえ何とかなれば,RSSを弄くるツールとしては完璧に近いと思うんですけどね.descriptionでNoMethodErrorが発生したらrescueしてtaglineを呼ぶ,とかするのは楽だろうけど*4,itemの方はnilが返ってきておるし….どーすりゃ良いんでしょうね.
おまけ:インストール時のエラー
インストールしてみると,
Installing RDoc documentation for simple-rss-1.1... lib/simple-rss.rb:nn:nn: ':' not followed by identified or operator # nには整数
っていうエラーメッセージがめちゃくちゃ出た!だけどirbで試すと
$ irb irb(main):001:0> require 'rubygems' => true irb(main):002:0> require 'simple-rss' => true
ってなったから問題無いっす.ソースを読んでいると,エラーが起こってる行にはこんなものが.
@@feed_tags = [ :id, :title, :subtitle, :link, :description, # 以下略
RDoc云々のトコでエラーが起こってるけど,RDocで":"は結構危ないのか?知らんけど.まぁGemServerのRDocはちゃんと読めてるし,問題無いってことで…良いよね(大した量のRDocでも無いが^^;).