RSS を YAML に変換する

ここまで学んだことの応用で、RSS をリモートから取得して YAML に変換してファイルに保存、というのをしたいです。

RSS2YAML というクラスを作って処理してみることにしました。

RSS2YAML.new('http://d.hatena.ne.jp/rubyo/rss').to_yaml

RSS::RDF オブジェクトを YAML に変換したものが返ります。以下はこのクラスを使った yaml2rss.rb です。引数にフィードの URI を与えると、標準出力に YAML がはき出されます。

#!/usr/local/bin/ruby

require 'open-uri'
require 'rss/1.0'
require 'yaml'

class RSS2YAML
  def initialize(url)
    @url = url
  end

  def to_yaml
    rss = self.parse_rss(@url)
    rss.to_yaml if rss
  end

  def get_remote(url)
    begin
      return Kernel.open(@url).read
    rescue OpenURI::HTTPError
      return nil
    end
  end

  def parse_rss(url)
    content = self.get_remote(url)
    if content
      begin 
        return RSS::Parser::parse(content)
      rescue RSS::InvalidRSSError
        return nil
      end
    end
  end

  public :to_yaml
  protected :get_remote, :parse_rss
end

if ARGV.size != 1
  puts "Usage: ruby rss2yaml.rb <url>"
  exit
end

puts RSS2YAML.new(ARGV.shift).to_yaml
  • 一応例外をキャッチするようにしてみました。クラス内部で例外が起こった場合に、それを補足して nil を返すというのは行儀という意味でどうなのでしょうか。こういう場合はどうするのがベストなのでしょう。
  • get_remote や parse_rss はクラス内だけで利用するので protected にしてみました。

このスクリプトを実行して、

$ ruby rss2yaml.rb http://d.hatena.ne.jp/rubyo/rss > rss.yaml

とリダイレクトで保存したところ、うまく保存できました。

復元用のスクリプトも書いてみます。

#!/usr/local/bin/ruby

require 'yaml'
require 'rss/1.0'

rss = YAML::load(ARGF.read)

rss.items.each do |item|
  puts item.link
end

ARGF を使ったフィルタにしてみました。

$ cat rss.yaml | ruby yaml2rss.rb
http://d.hatena.ne.jp/rubyo/20060402#1143961325
http://d.hatena.ne.jp/rubyo/20060402#1143960117
nil

実行結果が正しくありません。途中で nil が返ってきています。なぜでしょうか...。

RSSYAML に変換するにあたって、RSS::RDF オブジェクトを to_yaml しているので、復元されたものは RSS::RDF オブジェクトになります。本当は復元したものは単なるデータ構造でオブジェクトではない...というものにしたいところです。こういう場合は RSS::RDF オブジェクトから Hash などを作って to_yaml するのが一般的だったりするのでしょうか、まだよく分かっていません。