RSSフィードを集約したフィードを生成するWebアプリをSinatraで作ってみた
久し振りのプログラミング記事更新。
ボカロ関連のニュース情報を集めたフィードが欲しいと思い、RSSフィードを集約したフィードを生成するWebアプリをSinatraで作ってみた。
完成形は、下記のURLより参照できる。
Vocafeeds - ボカロ関連ニュース集約フィード
RSSの解析と生成には、標準のrssライブラリを使用。
GoogleアラートのフィードがATOM形式でrssライブラリでは解析できないので、REXMLライブラリで解析。
コードは下記のようになった(一部抜粋)。
hatenaメソッドがRSSの解析、add_itemメソッドがATOMの解析に相当。
require 'rubygems' require 'sinatra' require 'date' require 'open-uri' require 'rss' require 'rexml/document' configure do HATENA_URL = 'http://b.hatena.ne.jp/t/VOCALOID?sort=hot&threshold=&mode=rss' VOCALOID_GUIDE_URL = 'http://vocaloguide.com/feed' GOOGLE_ALERT_NEWS_VOCALOID_URL = 'http://www.google.com/alerts/feeds/11697367392137858374/16433312303441767819' GOOGLE_ALERT_NEWS_CHARACTER_URL = 'http://www.google.com/alerts/feeds/11697367392137858374/4844081763401052883' GOOGLE_ALERT_VOCALOID_URL = 'http://www.google.com/alerts/feeds/11697367392137858374/12241483289961948968' GOOGLE_ALERT_VOCALOID_ENGLISH_URL = 'http://www.google.com/alerts/feeds/11697367392137858374/7009353441646457352' end get '/feeds' do output = RSS::Maker.make("1.0") do |maker| maker.channel.about = "http://vocafeeds.champl.org/feeds" maker.channel.title = "Vocafeeds ボカロ関連ニュース集約フィード" maker.channel.description = "ボカロ関連ニュースのフィードを集約したフィード。" maker.channel.link = "http://vocafeeds.champl.org/" maker.items.do_sort = true hatena(maker) add_item(GOOGLE_ALERT_NEWS_VOCALOID_URL, maker) add_item(GOOGLE_ALERT_NEWS_CHARACTER_URL, maker) add_item(GOOGLE_ALERT_VOCALOID_URL, maker) add_item(GOOGLE_ALERT_VOCALOID_ENGLISH_URL, maker) add_item(VOCALOID_GUIDE_URL, maker) end content_type "application/xml" output.to_s end def hatena(maker) open HATENA_URL do |http| hatena = RSS::Parser.parse(http.read) hatena.items.each do |entry| next if entry.link =~ %r{http://www.nicovideo.jp/watch/} maker.items.new_item do |item| item.link = entry.link item.title = entry.title item.description = entry.description item.date = entry.date end end end end def make_rss(about, title, description, link, &block) output = RSS::Maker.make("1.0") do |maker| maker.channel.about = about maker.channel.title = title maker.channel.description = description maker.channel.link = link maker.items.do_sort = true block.call(maker) if maker.items.empty? then logger.info "empty!" maker.items.new_item do |item| item.link = "http://vocafeeds.champl.org/" item.title = "(no entry)" item.description = "エントリがありません" item.date = Time.now end end end content_type "application/xml" output.to_s end def add_item(url, maker) open url do |http| doc = REXML::Document.new(http.read) REXML::XPath.match(doc,"feed/entry").each do |entry| maker.items.new_item do |item| item.link = REXML::XPath.first(entry, "link").attributes["href"] item.title = REXML::XPath.first(entry, "title").text item.description = REXML::XPath.first(entry, "content").text item.date = REXML::XPath.first(entry, "updated").text end end end end