RSS maker on Ruby(ゴルゴ31篇)
(2009-04-27追記 Google App EngineでRSS - 鯨飲馬食コードにリンクあり)
「RSS on Ruby - 鯨飲馬食コード」で書いた、「ゴルゴ31」のRSSを出力するRubyのスクリプトをメモしておく。ごちゃごちゃしてるしエラー処理も考えずにアドホックに作ったものなので役に立つかは分からないけど。
以下コード。まずMy_RSSクラスから。
require 'uri' require 'net/http' Net::HTTP.version_1_2 require 'rss' require 'cgi' require 'stringio' class My_RSS @target_url = "" @target_name = "" @target_description = "" @rss_url = "" attr_accessor :target_url, :target_name, :target_description, :rss_url @start_line = // @end_line = // @cond_of_para =// @cond_of_anchor = // attr_accessor :start_line, :end_line, :cond_of_para, :cond_of_anchor @num_link = 0 @num_title = 0 @num_description = 0 @num_rest = 0 attr_accessor :num_link, :num_title, :num_description, :num_rest @a_link = [] @a_title = [] @a_description = [] def scan_body(body) buffer = "" a_link = [] a_title = [] a_description = [] flag = 0 StringIO.open(body).each do |line| line = CGI::unescapeHTML(line) if flag == 0 && line =~ @start_line flag = 1 elsif flag == 1 && line =~ @end_line break end if flag > 0 buffer = buffer + line.chomp if buffer =~ @cond_of_anchor link = $~[@num_link] title = $~[@num_title] description = $~[@num_description] rest = $~[@num_rest] if link =~ /^http\:\/\// a_link.push(link) a_title.push(CGI::escapeHTML(title)) a_description.push(description) end buffer = rest end end end @a_link = a_link @a_title = a_title @a_description = a_description end def make_rss i = 0 rss = RSS::Maker.make("1.0") do |maker| maker.channel.about = @rss_url maker.channel.title = @target_name maker.channel.description = @target_description maker.channel.link = @target_url while i < @a_link.size maker.items.new_item do |item| item.link = @a_link[i].to_s item.title = @a_title[i].to_s item.description = @a_description[i].to_s end i+=1 end end return rss end end
単に正規表現でマッチした部分を抜き出しているだけ。CGI::escapeHTMLで文字列をエスケープしてるけど必要ないかもしれない。上のクラスをMy_RSS.rbに保存したとして、以下のコードで実行する。
require 'My_RSS' require 'time' require 'kconv' $KCODE = "utf8" rss = My_RSS.new rss.target_url = 'http://www.golgo31.net/' rss.target_name = Kconv::toutf8('ゴルゴ31') rss.target_description = Kconv::toutf8('ゴルゴ31(http://www.golgo31.net/)の俺専用RSS') filename = 'golgo31.xml' rss.rss_url = 'http://yourhost.com/' + filename rss.start_line = /\<a name=\"(\d*?)\"/i rss.end_line = /\<\/font\>\<\/td\>\<\/tr\>/i rss.cond_of_anchor = /\<a href=\"(.*?)\"(.*?)\>(.*?)\<\/a\>(?:\<BR\>)?(.*?)\<BR\>\<BR\>(.*)/i rss.num_link = 1 rss.num_title = 3 rss.num_description = 4 rss.num_rest = 5 # sinseに10時間前をセット since = ( 0*(24*60*60) + 10*(60*60) + 0*(60) + 0 ) time = Time.now - since uri = URI.parse(rss.target_url) http = Net::HTTP.new(uri.host) # since秒以内に更新があったかを問い合わせ response = http.get(uri.path, {'if-modified-since' => time.httpdate}) # レスポンスコードが200ならファイルに書き出し if response.code.to_i == 200 rss.scan_body(Kconv::toutf8(response.body)) output = open(filename, "w") made_rss = rss.make_rss output.print made_rss output.close end
こんな感じで、今のところ安定して動作しているみたい(「RSSログ Index of /rss」)。cronを設定して定期的に実行するといいよ。
一応書いておくけど、私は普段個人ニュースサイトなるものを見ない。今回RSS(RDF Site Summary)を作ったのも、単にSemantic Webの思想に興味を持っているから。サイトの情報の要約が欲しかっただけで、別に更新情報をいち早く手に入れるためではないよ。
使えそうだなと思ったら改変していろんなサイトのリンクベースのRSSを作るといいよ。そして公開してくれると嬉しいな。