みなさん、こんにちは(・∀・)
rubyの標準RSSライブラリが思ったよりも高機能でびっくりしたので、gemを使わずにAtomとRssのParserを作ってみたので、そのへんのやり方をメモしておきますm(
)m
標準ライブラリを使用する場合は、下記のような形でhttpリクエストを送信したParseされたRSSフィードを取得することができます👀
require 'rss'
rss_source = Net::HTTP.get(URI.parse(endpoint))
rss = RSS::Parser.parse(rss_source)
=>
RSS::Parser.parse
の返り値は、引数で渡されたRSSの形式によって
、Rssの場合はRSS::Rss
、Atomの場合は、RSS::Atom::Feed
のオブジェクトが返却されます。(デフォルトでAtomまで対応してる🙌)
厳密には、下記とのこと
下記に詳細が乗っています👀
https://docs.ruby-lang.org/ja/latest/library/rss.html
共通のプロパティを持つオブジェクトを返却するRSSParserを作ってみる
標準ライブラリでAtomでもRssでも共通のオブジェクトを返却するRSSParserを作ってみようと思います👩🔧
イメージは下記のような感じ👀
RssCliant.new(endpoint).parsed_items
=> [
@description="みなさん、...",
@eye_catching_image="https://cdn.blog.st-hatena.com/images/theme/og-image-1500.png",
@link="https://madogiwa0124.hatenablog.com/entry/2019/03/09/194825",
@published_at=2019-03-09 19:48:25 +0900,
@title="vue-cliで作ったアプリをGithub Pagesでサクッとリリースする">,
@description=
"自分が作っている...",
@eye_catching_image="https://cdn-ak.f.st-hatena.com/images/fotolife/m/madogiwa0124/20190303/20190303213625.gif",
@link="https://madogiwa0124.hatenablog.com/entry/2019/03/03/214203",
@published_at=2019-03-03 21:42:03 +0900,
@title="railsとVueを使って無限スクロール機能を実装するMEMO🌀">,
まずはCliant部分を作ってみる
まずは下記のようなRssCliant
をというClassを作ってみました👀
endpointを受け取って標準ライブラリを使ってParse、その後AtomかRssかによって使用するParserを切り替え共通のオブジェクトを返却します。
class RssClient
def initialize(endpoint)
@endpoint = endpoint
@rss_source = Net::HTTP.get(URI.parse(endpoint))
end
attr_reader :endpoint, :rss_source
def parsed_rss!
RSS::Parser.parse(rss_source)
rescue RSS::InvalidRSSError
RSS::Parser.parse(rss_source, false)
end
def parsed_items
parsed_xml = parsed_rss!
case parsed_xml.class.name
when 'RSS::Atom::Feed' then Parser::Atom.call(parsed_xml)
when 'RSS::Rss' then Parser::Rss.call(parsed_xml)
else []
end
end
end
Rss.parse
でParseされたXMLを引数をもとに、build_parsed_item
でPasedItem
という共通のオブジェクトを生成し、それらのリストを返却するようにしています🙌
他の形式に対応する場合はParser::Hoge
が増えていくようなイメージですね👀
※またAtomの場合は、記事のアイキャッチ画像の取得方法が、ちょっと不明だったので一旦nil
を設定するようにしてます💦
class Parser::Rss
def self.call(parsed_xml)
new.call(parsed_xml)
end
def call(parsed_xml)
@parsed_xml = parsed_xml
items
end
attr_reader :parsed_xml
def items
@items = parsed_xml.items.map { |item| build_parsed_item(item) }
end
def build_parsed_item(item)
Parser::ParsedItem.new(
title: item.title,
description: item.description,
published_at: item.pubDate,
link: item.link,
eye_catching_image: item.enclosure&.url
)
end
end
class Parser::Atom
def self.call(parsed_xml)
new.call(parsed_xml)
end
def call(parsed_xml)
@parsed_xml = parsed_xml
items
end
attr_reader :parsed_xml
def items
@items = parsed_xml.entries.map { |entry| build_parsed_item(entry) }
end
def build_parsed_item(item)
Parser::ParsedItem.new(
title: item.title.content,
description: item.content.content,
published_at: item.published.content,
link: item.link.href,
eye_catching_image: nil
)
end
end
完成形
これでイメージどおりの完成形ができました🙌
RssCliant.new(endpoint).parsed_items
=> [
@description="みなさん、...",
@eye_catching_image="https://cdn.blog.st-hatena.com/images/theme/og-image-1500.png",
@link="https://madogiwa0124.hatenablog.com/entry/2019/03/09/194825",
@published_at=2019-03-09 19:48:25 +0900,
@title="vue-cliで作ったアプリをGithub Pagesでサクッとリリースする">,
@description=
"自分が作っている...",
@eye_catching_image="https://cdn-ak.f.st-hatena.com/images/fotolife/m/madogiwa0124/20190303/20190303213625.gif",
@link="https://madogiwa0124.hatenablog.com/entry/2019/03/03/214203",
@published_at=2019-03-03 21:42:03 +0900,
@title="railsとVueを使って無限スクロール機能を実装するMEMO🌀">,
おわりに
今回はRubyの標準ライブラリだけを使ってRssParserを実装してみました。RssParserはFeedjira等のGemが有名ですが、そんなに凝ったことしないのであればRubyの標準ライブラリが使いやすく高機能なので充分なのでは?という気持ちになりました🙌
他にも標準ライブラリには便利そうな機能がありそうだったので、ちょっと見てみると良さそうですね👀