|
Ruby で RSS 解析する際の覚え書き。 概要 †Ruby 1.8.2 から RSS 解析ライブラリが標準搭載。 必要なもの †
1.8.2 だと RSS::DublinCoreModel? に dc_subjects がないのでバージョンを上げた。 ラッパークラス サンプル †(get_rss.rb)
require 'rss/1.0'
require 'open-uri'
class RssSite
attr_accessor:url
attr_accessor:content
attr_accessor:rss
def initialize(url)
@url = url
end
def get()
@content = ""
open(url) {|u|
@content = u.read
}
parse()
end
def parse()
begin
@rss = RSS::Parser::parse(content)
rescue RSS::InvalidRSSError
@rss = RSS::Parser::parse(content,false)
end
end
def save(file)
File.open(file,'w') {|f|
f.print(@content)
}
end
def each_item
rss.items.each {|i| yield(i) }
end
end
class RSSTrace
def initialize(url)
@url = url
@start = 0
@max = 500
@sep = 25
@debugout = STDERR
end
def get
@start.step(@max,@sep) {|i|
b_url = "#{@url}&of=#{i}"
r = RssSite.new b_url
begin
r.get
rescue
@debugout.puts $!
next
end
@debugout.puts "get #{b_url}"
r.rss.items.each {|i| yield i }
}
end
attr_accessor :url, :start, :max, :sep, :debugout
end
使い方 †C:\>irb
irb(main):001:0> require 'get_rss.rb'
=> true
irb(main):002:0> r = RssSite.new("http://internet.kill.jp/int.rdf")
=> #<RssSite:0x2ff4d48 @url="http://internet.kill.jp/int.rdf">
irb(main):003:0> r.get
=> (略)
irb(main):004:0> r.save("int.rdf")
=> nil
irb(main):005:0> r.url = "int.rdf"
=> "int.rdf"
irb(main):006:0> r.get
=> (略)
このように、ネットワークとローカルファイルはほぼシームレス。 open-uri すごい。 応用 †2006-10-18 †拡張クラス RSSTrace を作ってみた。 事実上ほとんどはてな用だけど、はてなブックマークの RSS のように位置を指定しながら次々取っていくインターフェースのトレーサ。 get メソッドの引数にブロックを渡すと RSS の item ごとに評価します。 http://b.hatena.ne.jp/xx-internet/ のブックマーク URL を最大 10000 件表示するサンプル。 require 'get_rss.rb'
t = RSSTrace.new("http://b.hatena.ne.jp/xx-internet/rss?")
t.max = 10000
t.get {|item| puts item.link }
2006-03-18 †404 blog not found - 最近のはてブで流行している7つのタグを見て追試。 はてブの RSS は dc:subject にタグが書いてあるので、以下のようにしてみた。 require 'get_rss'
require 'rss/dublincore'
r = RssSite.new("http://b.hatena.ne.jp/entrylist?mode=rss&sort=hot&threshold=5")
r.get()
r.save("hb_hot.xml")
r.rss.items.each{|i|
i.dc_subject.each{|s|
puts s.content
}
}
NG 。これだと最初の dc_subject しか取っていない。 軽く調べて dc_subjects を使えばいいらしい、 と知り、そっちを使う。(ついでに Ruby 自体を 1.8.2 -> 1.8.4 にアップデートしてしまった) r.rss.items.each{|i|
i.dc_subjects.each{|s|
puts s.content
}
}
これでなんとなく動いたので、ロジックをいじって完成。なんだかんだで一時間以上かかった。 r = RssSite.new( "http://b.hatena.ne.jp/hotentry?mode=rss")
r.get()
r.save("hb_hotentry.xml")
tags = Hash.new {|hash,key| hash[key] = 0 }
r.rss.items.each{|i|
begin
r_entry = RssSite.new( 'http://b.hatena.ne.jp/entry/rss/' + i.link)
puts "get #{r_entry.url}"
r_entry.get()
r_entry.rss.items.each{|j|
j.dc_subjects.each{|s|
tags[s.content] += 1
}
}
rescue
STDERR.puts $!
end
}
tags.to_a.sort{|a, b|
(b[1] <=> a[1]) * 2 + (a[0] <=> b[0])
}.each {|key, item|
puts "#{key} #{item}"
}
javascript 176 web 141 2ch 93 sns 89 prototype.js 85 ajax 83 design 73 SNS 55 JavaScript 52 webデザイン 52 またちょっと結果が違う。 あと、 get_rss.rb の parse 部分を別メソッドにしてみた。 こうすると r.get() # あ、 DublinCore のデータ欲しい require 'rss/dublincore' # 再解析 r.parse() というふざけた使い方が可能に。 参考リンク †
更新履歴 †
最新の10件を表示しています。 コメントページを参照 |