railsでruby標準のrss
gemを使用して、RSSフィードの取得・登録処理を実装した。
環境
やったこと
gemの追加
rss
はbundled gemなので、railsで使う場合はGemfileに以下を追加してbundle install
する。
# Gemfile gem 'rss'
RSSのパース、DBへの登録
rss
gemを使ってRSSをパースする場合はRSS::Parser.parse
メソッドを使用する。
.items
とすることで、オブジェクトの配列が返ってくる
# 戻り値としてオブジェクトの配列が返ってくる RSS::Parser.parse('https://example.com/rss').items
パース後のオブジェクトはフィードの形式毎にクラスが異なるだけでなく、タイトルやリンクなどを取得する際に指定するプロパティも異なるため、フィードの形式毎に別の登録処理を実行する。
※フィードの形式毎にクラスを定義しても良い
# app/models/feed.rb class Feed < ApplicationRecord def self.fetch_and_save(feed_url) # RSSをパース rss_items = RSS::Parser.parse(feed_url).items rss_items.each do |item| # プロパティの種類が異なるため、フィードの形式毎に登録処理を分ける case item.class.name # RSS1.0の登録処理 when 'RSS::RDF::Item' then Feed.save_rdf_feed(item) # RSS2.0の登録処理 when 'RSS::Rss::Channel::Item' then Feed.save_rss_feed(item) # Atomの登録処理 when 'RSS::Atom::Feed::Entry' then Feed.save_atom_feed(item) end end end . . .
RSS1.0の登録処理
RSS1.0、およびrss
gemで対応しているRSSのモジュール(2023年9月2日現在)では、記事ごとに画像を設定できないようなので、RSS1.0では画像のURLにnil
を設定する。
# app/models/feed.rb def self.save_rdf_feed(rdf_item) Feed.create( title: rdf_item.title, url: rdf_item.link, summary: rdf_item.description, image_url: nil, published_at: rdf_item.dc_date ) end
RSS2.0の登録処理
enclosure
に関してはオプションで、当該xmlに存在しない場合がある。そのためrss_item.enclosure&.url
として、存在しないときは画像のURLにnil
を設定して登録する。
# app/models/feed.rb def self.save_rss_feed(user, rss_item) Feed.create( title: rss_item.title, url: rss_item.link, summary: rss_item.description, image_url: rss_item.enclosure&.url, published_at: rss_item.pubDate ) end
Atomの登録処理
AtomではRSS2.0のenclosure
のように画像の場合も明確にタグの種類が異なるわけではなく、複数存在するlink
の一つとして画像が設定されている。そのため、link
のtype
プロパティにimage
が設定されているものを探して画像のURLを取得する。こちらもRSS2.0と同様、存在しない場合があるため&.href
としている。
# app/models/feed.rb def self.save_atom_feed(user, atom_item) Feed.create( title: atom_item.title.content, url: atom_item.link.href, summary: atom_item.content.content, image_url: atom_item.links.find { |link| !link.type.nil? && link.type.include?('image') }&.href, published_at: atom_item.published.content ) end