Ruby 2.0.0 リファレンスマニュアル > ライブラリ一覧 > rssライブラリ

library rss

要約

RSS を扱うためのライブラリです。

参考

注意

RSS ParserはRSS 0.9x/1.0/2.0をサポートしていますが,RSS 0.90 はサポートしてません.ごめんなさい.

RSS のモジュールはそれぞれ、

をサポートしています。 ただし,Content モジュールは content:encoded しかサポートしていません.

パース

RSS をパースしたい場合は RSS::Parser クラスを使います。 RSS::Parser.parse は String の RSSを パースします(使用するXMLパー サによっては File や IO オブジェクトなどでもパース可能です)。

をそれぞれ返します。パースした String が well formed な XML で無い場合は, 例外 RSS::NotWellFormedError が発生します。well formed な XML だが,RSS 0.9x/1.0/2.0 のいずれでもない場合は,nil が返りま す.

例えば、RSS 1.0 をバリデーション付きでパースするには以下のよ うにします。ここで、変数 rss_source には RSS 1.0 形式の文 字列が格納されているものとします。

require 'rss'
rss = RSS::Parser.parse(rss_source, true)

RSS::Parser.parse の第二引数は省略すると true が指定されたもの とみなされるので、これは以下のようにも書けます。

require 'rss'
rss = RSS::Parser.parse(rss_source)

最初はバリデーション付きでパースして,valid ではない RSS だった 場合はバリデーション無しでパースするには以下のように書きます。

require 'rss'
rss = nil
begin
  rss = RSS::Parser.parse(rss_source)
rescue RSS::InvalidRSSError
  rss = RSS::Parser.parse(rss_source, false)
end

これは rss_source が RSS 0.9x/1.0/2.0 のどれか分からない時 にも有効です。RSS 1.0としてバリデー ション付きでパースし、バリデーションに失敗すると RSS 0.9x/(壊 れた)1.0/2.0 のいずれかとしてパースします。

知らない要素の扱い

パーサはデフォルトでは知らない要素(仕様書に規定されていない 要素)を無視します。もし、知らない要素に遭遇した時に例外を発 生させたければ,RSS::Parser.parse の第三引数に false を指定して ください。こうすると、パース中に知らない要素に遭遇した時に RSS::UnknownTagError 例外が発生します。

以下のようにすると,より厳密にRSS 1.0をパースできます。

RSS::Parser.parse(rss_source, true, false)

パースされたRSS

RSS はパースされると String オブジェクトから RSS::RDF, RSS::RDF::Channel, RSS::Rss 等のオブジェクトになります。各オ ブジェクトで子要素オブジェクトにアクセスするために,要素名と 同じ名前のアクセサがあります。

リーダ(reader)

rdf:RDF 要素の子要素である channel 要素を参照するには,以下のよう にします。

rss = RSS::Parser.parse(rss_source)
rss.channel # => /rdf:RDF/channel要素; RSS::RDF::Channel

もし、要素が子要素も属性も持たない場合は String が返ってきます。 その要素が省略可能ならばnilが返って来るかもしれません。これ は要素が子要素または属性を持つ場合も同様です。

rss = RSS::Parser.parse(rss_source)
rss.channel.description # => /rdf:RDF/channel/text(); String

属性にアクセスする時も同様です。channel要素のrdf:about属性に アクセスするには以下のようにします。属性の値はStringかnilで す。

rss = RSS::Parser.parse(rss_source)
rss.channel.about # => /rdf:RDF/channel/@about属性; String または nil

同名の複数の子要素があるかもしれないときも同様です。ただし、 リーダに引数を指定しないと最初の子要素が返ってきます。例えば、 rdf:RDF要素の最初のitem要素にアクセスするには以下のようにし ます。

rss = RSS::Parser.parse(rss_source)
rss.item # => /rdf:RDF/item[1]要素; RSS::RDF::Item

3番目のitem要素にアクセスするには以下のようにします。省略さ れなかったリーダの引数はArray#[]の引数と同じように扱われます。

rss = RSS::Parser.parse(rss_source)
rss.item(2) # => /rdf:RDF/item[3]要素; RSS::RDF::Item

子要素すべてを取得したいときは要素名の複数形がリーダとなりま す。すべてのitem要素を取得するには以下のようにします。

rss = RSS::Parser.parse(rss_source)
rss.items # => /rdf:RDF/item要素の配列; [RSS::RDF::Item, ...]

ライタ(writer)

rdf:RDF要素の子要素であるchannel要素を設定するには以下のよう にします。RSS::RDF::Channel.newの第一引数にはrdf:about属性の 値を指定することもできます。

rss = RSS::Parser.parse(rss_source)
rss.channel = RSS::RDF::Channel.new(rdf_about_value)

属性値を設定する場合も同様です。

rss = RSS::Parser.parse(rss_source)
rss.channel.about = "http://cozmixng.www.cozmixng.org/"

同名の複数の子要素が存在する場合は少し異なります.要素名の複 数形でのメソッドで要素の配列を取得して,その配列に対して Array#<<やArray#[]=などを用いて要素を設定します.

rss = RSS::Parser.parse(rss_source)
item = RSS::RDF::Item.new(rdf_about_value)
rss.items << item
rss.items.last == item # => true

注意: item=/set_itemなどはRubyっぽくないので使わないでくださ い.

出力

RSS Parserといっているので誤解されがちですが,RSSを出力する こともできます.

基本

to_sするとRSS形式の文字列を返します.

RSSを出力する流れは以下のようになります.

xml-stylesheet

xml-stylesheetも出力することができます.

RSSのルート要素(RSS::RDFまたはRSS::Rss)オブジェ クトはxml_stylesheetsという名前の配列を持っています.この配 列にRSS::XMLStyleSheetオブジェクトを挿入することでRSS にxml-stylesheetを関連づけることができます.

rss.xml_stylesheets << RSS::XMLStyleSheet.new(...)

RSS::XMLStyleSheet.newには以下のようなHashまたは 連想配列を渡します.作成されるRSS::XMLStyleSheetオブジェ クトは与えられた引数によって初期化されます.

Hash:

{
  :href => "...",
  :type => "...",
  :title => "...",
  :media => "...",
  :charset => "...",
  :alternate => "...",
}

連想配列:

[
  [:href, "..."],
  [:type, "..."],
  [:title, "..."],
  [:media, "..."],
  [:charset, "..."],
  [:alternate, "..."],
]

全てのキーは省略可能です.

例えば,xml-stylesheetとしてsample.xslを指定する場合は以下の ようにします.

rss.xml_stylesheets << RSS::XMLStyleSheet.new({:href => "sample.xsl"})

本当は{:type => "text/xsl"}も指定しないといけないとこ ろですが,拡張子が.xslまたは,.cssの場合は適当に推測してくれ るので省略可能です.

RSSオブジェクトを作る

既存のRSSをパースせずに,一から新しくRSSを作成するにはRSS Makerが便利です.

以下のように使います.

require "rss"

rss = RSS::Maker.make("バージョン") do |maker|
  maker.XXX = YYY
  ...
end

例えば,

を生成するには以下のようにします.

require "rss"

rss = RSS::Maker.make("1.0") do |maker|
  maker.channel.about = "http://example.com/index.rdf"
  maker.channel.title = "Example"
  maker.channel.description = "Example Site"
  maker.channel.link = "http://example.com/"
end

もし,

エントリを含めたければ以下のようにします.

require "rss"

rss = RSS::Maker.make("1.0") do |maker|
  maker.channel.about = "http://example.com/index.rdf"
  maker.channel.title = "Example"
  maker.channel.description = "Example Site"
  maker.channel.link = "http://example.com/"

  item = maker.items.new_item
  item.link = "http://example.com/article.html"
  item.title = "Sample Article"
end

もし,先のエントリが

のものならこうします.

require "rss"

rss = RSS::Maker.make("1.0") do |maker|
  maker.channel.about = "http://example.com/index.rdf"
  maker.channel.title = "Example"
  maker.channel.description = "Example Site"
  maker.channel.link = "http://example.com/"

  item = maker.items.new_item
  item.link = "http://example.com/article.html"
  item.title = "Sample Article"
  item.date = Time.parse("2004/11/1 10:10")
end

サンプル中の

item.date = ...

item.dc_date = ...

でも構いません.#dc_date=は#date=の単なる別名で す.

さらに,

エントリを持つなら以下のようにします.

require "rss"

rss = RSS::Maker.make("1.0") do |maker|
  maker.channel.about = "http://example.com/index.rdf"
  maker.channel.title = "Example"
  maker.channel.description = "Example Site"
  maker.channel.link = "http://example.com/"

  item = maker.items.new_item
  item.link = "http://example.com/article.html"
  item.title = "Sample Article"
  item.date = Time.parse("2004/11/1 10:10")

  item = maker.items.new_item
  item.link = "http://example.com/article2.html"
  item.title = "Sample Article2"
  item.date = Time.parse("2004/11/2 10:10")
end

もし,更新日が新しい順に並び替えたければ

maker.items.do_sort = true

を追加し,以下のようにします.

require "rss"

rss = RSS::Maker.make("1.0") do |maker|
  maker.channel.about = "http://example.com/index.rdf"
  maker.channel.title = "Example"
  maker.channel.description = "Example Site"
  maker.channel.link = "http://example.com/"

  maker.items.do_sort = true

  item = maker.items.new_item
  item.link = "http://example.com/article.html"
  item.title = "Sample Article"
  item.date = Time.parse("2004/11/1 10:10")

  item = maker.items.new_item
  item.link = "http://example.com/article2.html"
  item.title = "Sample Article2"
  item.date = Time.parse("2004/11/2 10:10")
end

もし,サイトに

がある場合は以下のようにします.

require "rss"

rss = RSS::Maker.make("1.0") do |maker|
  maker.channel.about = "http://example.com/index.rdf"
  maker.channel.title = "Example"
  maker.channel.description = "Example Site"
  maker.channel.link = "http://example.com/"

  maker.items.do_sort = true

  item = maker.items.new_item
  item.link = "http://example.com/article.html"
  item.title = "Sample Article"
  item.date = Time.parse("2004/11/1 10:10")

  item = maker.items.new_item
  item.link = "http://example.com/article2.html"
  item.title = "Sample Article2"
  item.date = Time.parse("2004/11/2 10:10")

  maker.image.title = "Example Site"
  maker.image.url = "http://example.com/logo.png"
end

もし,

検索用CGIがあったら以下のようにします.

require "rss"

rss = RSS::Maker.make("1.0") do |maker|
  maker.channel.about = "http://example.com/index.rdf"
  maker.channel.title = "Example"
  maker.channel.description = "Example Site"
  maker.channel.link = "http://example.com/"

  maker.items.do_sort = true

  item = maker.items.new_item
  item.link = "http://example.com/article.html"
  item.title = "Sample Article"
  item.date = Time.parse("2004/11/1 10:10")

  item = maker.items.new_item
  item.link = "http://example.com/article2.html"
  item.title = "Sample Article2"
  item.date = Time.parse("2004/11/2 10:10")

  maker.image.title = "Example Site"
  maker.image.url = "http://example.com/logo.png"

  maker.textinput.title = "Search Example Site"
  maker.textinput.description = "Search Example Site's all text"
  maker.textinput.name = "keyword"
  maker.textinput.link = "http://example.com/search.cgi"
end

もし,

xml-stylesheetを追加したい場合は以下のようにします.

require "rss"

rss = RSS::Maker.make("1.0") do |maker|
  xss = maker.xml_stylesheets.new_xml_stylesheet
  xss.href = "http://example.com/index.xsl"

  maker.channel.about = "http://example.com/index.rdf"
  maker.channel.title = "Example"
  maker.channel.description = "Example Site"
  maker.channel.link = "http://example.com/"

  maker.items.do_sort = true

  item = maker.items.new_item
  item.link = "http://example.com/article.html"
  item.title = "Sample Article"
  item.date = Time.parse("2004/11/1 10:10")

  item = maker.items.new_item
  item.link = "http://example.com/article2.html"
  item.title = "Sample Article2"
  item.date = Time.parse("2004/11/2 10:10")

  maker.image.title = "Example Site"
  maker.image.url = "http://example.com/logo.png"

  maker.textinput.title = "Search Example Site"
  maker.textinput.description = "Search Example Site's all text"
  maker.textinput.name = "keyword"
  maker.textinput.link = "http://example.com/search.cgi"
end

もし,RSS 2.0を生成したい場合は以下のように, RSS::Maker.makeの第一引数を変更します.

require "rss"

rss = RSS::Maker.make("2.0") do |maker|
  xss = maker.xml_stylesheets.new_xml_stylesheet
  xss.href = "http://example.com/index.xsl"

  maker.channel.about = "http://example.com/index.rdf"
  maker.channel.title = "Example"
  maker.channel.description = "Example Site"
  maker.channel.link = "http://example.com/"

  maker.items.do_sort = true

  item = maker.items.new_item
  item.link = "http://example.com/article.html"
  item.title = "Sample Article"
  item.date = Time.parse("2004/11/1 10:10")

  item = maker.items.new_item
  item.link = "http://example.com/article2.html"
  item.title = "Sample Article2"
  item.date = Time.parse("2004/11/2 10:10")

  maker.image.title = "Example Site"
  maker.image.url = "http://example.com/logo.png"

  maker.textinput.title = "Search Example Site"
  maker.textinput.description = "Search Example Site's all text"
  maker.textinput.name = "keyword"
  maker.textinput.link = "http://example.com/search.cgi"
end

もし,RSS 0.91を生成したい場合は,RSS 2.0の場合と同様に RSS::Maker.make の第一引数を"0.91"に変更します.

サンプル

RSS Parser のサンプルスクリプトをいくつか紹介します.これらの スクリプトは sample/ 以下に入っています.

サンプル1 - 項目一覧

それでは、複数のRSSをパースしてitem要素を表示するスクリプト を書いてみましょう。

まず、RSS 0.9x/1.0/2.0をパースできるように以下のようにrequireします。

require 'rss'

パースするRSSはファイルに保存されていて引数で与えられるものとします。

ARGV.each do |fname|
  rss_source = nil
  File.open(fname) do |f|
    rss_source = f.read
  end

  rss = nil
  begin
    rss = RSS::Parser.parse(rss_source, false)
  rescue RSS::Error
  end

  if rss.nil?
    puts "#{fname}はRSS 0.9x/1.0/2.0のいずれでもありません。"
  else
    print_items(rss)
  end
end

あとはprint_itemsというメソッドを定義するだけです。

RSS::RDFとRSS::Rssには便利のためにitemsというメソッドとimage というメソッドが定義されています。

itemsはRSS::RDFの場合は全ての/rdf:RDF/item要素を配列で返しま す。RSS::Rssの場合は全ての/rss/channel/item要素を配列で返し ます。

imageはRSS::RDFの場合は/rdf:RDF/image要素を返します。 RSS::Rssの場合は/rss/channel/image要素を返します。

def print_items(rss)
  rss.items.each do |item|
    puts "#{item.title} : #{item.description}"
  end
end

出力する文字コードを変更するにはRSS::RDF#output_encoding=ま たはRSS::Rss#output_encoding=が使えます。もし、変換できない エンコーディングを指定された場合は RSS::UnknownConversionMethodError例外が発生します。

先程のprint_itemsをEUC-JPで出力するように書き換えてみましょう。

def print_items(rss)
  begin
    rss.output_encoding = "EUC-JP"
  rescue RSS::UnknownConversionMethodError
  end
  rss.items.each do |item|
    puts "#{item.title} : #{item.description}"
  end
end

サンプル2 - 更新順表示

次はDublin Coreモジュールのdate属性を使って更新順にitemを表 示してみましょう。

最初に現れたDublin Coreモジュールの要素にアクセスするには 「dc_要素名」というアクセサが用意されています。全ての要素の 配列にアクセスするには「dc_要素の複数形」とします. (rights の場合は dc_rightses とする必要があります)

複数形でアクセスした場合は「要素の内容を表す文字列」ではなく, 「要素を表すオブジェクト」の配列が返ります.「要素を表すオブ ジェクト」から「要素の内容を表す文字列」を取得するには contentメソッドやその別名であるvalueメソッドを利 用します.「要素の内容を表す文字列」を設定するには content=メソッドやその別名であるvalue=メソッドを 利用します.

rss.channel.dc_title  # => 「要素の内容を表す文字列」
                      # ("My site"など)

rss.channel.dc_titles # => 「要素を表すオブジェクト」の配列
                      # ([DublinCoreTitleオブジェクト, ...])

rss.channel.dc_titles.collect {|title| title.value}
                      # => 「要素の内容を表す文字列」の配列
                      # (["My site", ...]など)

rss.channel.dc_titles.first.value == rss.channel.dc_title
                      # => true
# 厳密にはこう
first_title = rss.channel.dc_titles.first
first_title = first_title.value if first_title
first_title == rss.channel.dc_title
                      # => true

ちなみにSyndicationモジュールの要素にアクセスするには「sy_要 素名」というアクセサが,Contentモジュールの要素にアクセスす るには「content_要素名」というアクセサが用意されています。

サンプル1と同じようにパースするRSSはファイルに保存されていて 引数で与えられるものとします。

items = []
ARGV.each do |fname|
  rss_source = nil
  File.open(fname) do |f|
    rss_source = f.read
  end

  rss = nil
  begin
    rss = RSS::Parser.parse(rss_source, true)
  rescue RSS::Error
  end

  if rss.nil?
    puts "#{fname}はRSS 1.0ではありません。"
  else
    begin
      rss.output_encoding = "euc-jp"
    rescue RSS::UnknownConversionMethodError
    end
    rss.items.each do |item|
      items << item if item.dc_date
    end
  end
end
print_items(items)

あとはprint_itemsというメソッドを定義するだけです。

Item#dc_dateはTimeオブジェクトかnilを返します。引数の itemsにはdc_dateがnilではないものしか含まれていないは ずなので以下のようにソートできます。

def print_items(items)
  items.sort do |x, y|
    y.dc_date <=> x.dc_date
  end.each do |item|
    puts "#{item.dc_date.localtime.iso8601} : #{item.title} : #{item.description}"
  end
end

クラス

RSS::Element
  RSS::ImageFaviconModel::ImageFavicon
  RSS::ImageItemModel::ImageItem
  RSS::RDF
  RSS::RDF::Channel
  RSS::RDF::Channel::Image
  RSS::RDF::Channel::ImageFavicon
  RSS::RDF::Channel::Items
  RSS::RDF::Channel::Textinput
  RSS::RDF::Image
  RSS::RDF::Item
  RSS::RDF::Textinput
  RSS::Rss
  RSS::Rss::Channel
  RSS::Rss::Channel::Cloud
  RSS::Rss::Channel::Image
  RSS::Rss::Channel::Item
  RSS::Rss::Channel::Item::Category
  RSS::Rss::Channel::Item::Enclosure
  RSS::Rss::Channel::Item::Guid
  RSS::Rss::Channel::Item::Source
  RSS::Rss::Channel::TextInput
  RSS::Rss::SkipDays
  RSS::Rss::SkipHours
  RSS::TaxonomyTopicModel::TaxonomyTopic
  RSS::TaxonomyTopicsModel::TaxonomyTopics
  RSS::TrackBackModel10::TrackBackAbout
  RSS::TrackBackModel10::TrackBackPing
  RSS::TrackBackModel20::TrackBackAbout
  RSS::TrackBackModel20::TrackBackPing
RSS::Maker::Base
  RSS::Maker::ItemsBase
   RSS::Maker::RSS09::Items
    RSS::Maker::RSS20::Items
   RSS::Maker::RSS10::Items
  RSS::Maker::ItemsBase::ItemBase::EnclosureBase
   RSS::Maker::RSS09::Items::Item::Enclosure
    RSS::Maker::RSS20::Items::Item::Enclosure

RSS 2.0を生成するときだけ利用されます.

  RSS::Maker::ItemsBase::ItemBase::GuidBase
   RSS::Maker::RSS09::Items::Item::Guid
    RSS::Maker::RSS20::Items::Item::Guid

RSS 2.0を生成するときだけ利用されます.

  RSS::Maker::ItemsBase::ItemBase::SourceBase
   RSS::Maker::RSS09::Items::Item::Source
    RSS::Maker::RSS20::Items::Item::Source

RSS 2.0を生成するときだけ利用されます.

RSS::Maker::ChannelBase

channel要素の値を設定します.

  RSS::Maker::RSS09::Channel
   RSS::Maker::RSS20::Channel
  RSS::Maker::RSS10::Channel
RSS::Maker::ChannelBase::CategoriesBase
  RSS::Maker::RSS09::Channel::Categories
   RSS::Maker::RSS20::Channel::Categories
  RSS::Maker::RSS10::Channel::Categories
RSS::Maker::ChannelBase::CategoriesBase::CategoryBase

categoryは maker.channel.categories.new_categoryで作成されたオ ブジェクトとします.

  RSS::Maker::RSS09::Channel::Categories::Category
   RSS::Maker::RSS20::Channel::Categories::Category
  RSS::Maker::RSS10::Channel::Categories::Category
RSS::Maker::ChannelBase::SkipDaysBase

RSS 0.91/2.0を生成するときだけ利用されます.

  RSS::Maker::RSS09::Channel::SkipDays
   RSS::Maker::RSS20::Channel::SkipDays
RSS::Maker::ChannelBase::SkipDaysBase::DayBase

dayは maker.channel.skipDays.new_dayで作成されたオ ブジェクトとします.

  RSS::Maker::RSS09::Channel::SkipDays::Day
   RSS::Maker::RSS20::Channel::SkipDays::Day
RSS::Maker::ChannelBase::SkipHoursBase
  RSS::Maker::RSS09::Channel::SkipHours
   RSS::Maker::RSS20::Channel::SkipHours
RSS::Maker::ChannelBase::SkipHoursBase::HourBase

hourは maker.channel.skipHours.new_hourで作成されたオ ブジェクトとします.

  RSS::Maker::RSS09::Channel::SkipHours::Hour
   RSS::Maker::RSS20::Channel::SkipHours::Hour
RSS::Maker::ImageBase

RSS 1.0の場合はurl,title, maker.channel.link,maker.channelが適切に設定さ れている必要があります.

  RSS::Maker::RSS09::Image
   RSS::Maker::RSS20::Image
  RSS::Maker::RSS10::Image
RSS::Maker::ItemsBase::ItemBase

itemはmaker.items.new_itemで作成されたオブジェク トとします.

  RSS::Maker::RSS09::Items::Item
   RSS::Maker::RSS20::Items::Item
  RSS::Maker::RSS10::Items::Item
RSS::Maker::ItemsBase::ItemBase::CategoriesBase
  RSS::Maker::RSS09::Items::Item::Categories
   RSS::Maker::RSS20::Items::Item::Categories

RSS 2.0を生成するときだけ利用されます.

RSS::Maker::RSSBase

RSSのルート要素を生成するオブジェクトです.

  RSS::Maker::RSS10
  RSS::Maker::RSS20
RSS::Maker::TextinputBase

RSS 1.0の場合はtitle,description,name, link,maker.channelを適切に設定する必要がありま す.

  RSS::Maker::RSS09::Textinput
   RSS::Maker::RSS20::Textinput
  RSS::Maker::RSS10::Textinput
RSS::Maker::XMLStyleSheets::XMLStyleSheet

xml_stylesheetは maker.xml_stylesheet.new_xml_stylesheetで作成されたオ ブジェクトとします.

RSS::Parser
RSS::XMLStyleSheet

モジュール

DublinCoreModel
RSS::BaseTrackBackModel
RSS::ContentModel
RSS::DublinCoreModel

@todo

RSS::ImageFaviconModel
RSS::ImageItemModel
RSS::ImageModelUtils

@todo

RSS::Maker
RSS::RootElementMixin
RSS::SyndicationModel
RSS::TaxonomyTopicModel
RSS::TaxonomyTopicsModel
RSS::TrackBackModel10
RSS::TrackBackModel20
RSS::XMLStyleSheetMixin

例外クラス

RSS::Error
  RSS::ConversionError
  RSS::InvalidRSSError
   RSS::MissingAttributeError
   RSS::MissingTagError
   RSS::NotAvailableValueError
   RSS::NotExpectedTagError
   RSS::TooMuchTagError
   RSS::UnknownTagError
  RSS::NSError
  RSS::NotSetError
  RSS::NotValidXMLParser
  RSS::NotWellFormedError
  RSS::OverlappedPrefixError
  RSS::UnknownConversionMethodError
  RSS::XMLParserNotFound

追加・再定義されるメソッド

RSS::Rss::Channel#generator RSS::Rss::Channel#ttl RSS::Rss::Channel::Item#author RSS::Rss::Channel::Item#comments RSS::Rss::Channel::Item#guid RSS::Rss::Channel::Item#pubDate