Rubyでどう書く?:重複したRSSをまとめる
「ネットの話題を追いかけるために、はてブのホッテントリやlivedoor クリップの人気ページをRSSで取得しています。でも、重複していることも多いんです。助けてください」(32才 男性・家事手伝い)――よろしい、ならばRubyで書こう。
第4回目のテーマは「重複したRSSをまとめる」と題しまして、Rubyで複数のRSSから重複したエントリを除去する問題を出します。
問題
最近、はてなブックマークやlivedoor クリップなど、ユーザーが外部のサイトを集めて、その結果を出力するサービスが増えてきました。
ただ、一部のサイトを見ているだけで話題を追うことができるので便利なのですが、同じURLが複数のRSSにあり「もうこれは見たのに……」という事も多いですよね。
そこで今回は、複数のRSSを一つのRSSとして出力するプログラムを問題にします。
仕様
- RSSのURLは、コマンドラインから引数として1個以上与えられる。
- 結合した結果のRSSのタイトルおよび説明は、各引数のタイトルをつなげたものとする。
- 結合した結果のRSSのURLは第一引数のURLとする。
- フィードのリンク先が同一のものを同じフィードとして扱う。
- 出力順は第一引数のものを順に出力し、その後第二引数、第三引数のものを順に出力する(同じフィードとして扱うものは除外する)。
- 重複したものは前の引数の内容を出力する。
- 出力先は標準出力とする。
- 出力するRSSのバージョンは2.0
回答例
1 require 'rss' 2 3 rss_feeds = [] 4 rss_urls = [] 5 title="" 6 7 ARGV.each do | rss_url | 8 open(rss_url) do | http | 9 response = http.read 10 rss_results = RSS::Parser.parse(response, false) 11 12 if rss_results && rss_results.channel && rss_results.channel.title 13 title += " と " if title.size > 0 14 title += rss_results.channel.title 15 end 16 17 rss_results.items.each do | item | 18 unless rss_urls.include? item.link 19 rss_urls << item.link 20 rss_feeds << item 21 end 22 end 23 end 24 end 25 26 rss = RSS::Maker.make("2.0") do | writer | 27 writer.channel.title = title || "" 28 writer.channel.link = rss_urls[0] || "" 29 writer.channel.description = title || "" 30 rss_feeds.each do | feed | 31 feed.setup_maker(writer) 32 end 33 end 34 35 puts rss.to_s
試しに、livedoor クリップ 人気ページと、はてなブックマーク 人気エントリーを取得してみましょう。
ruby rss.rb http://clip.livedoor.com/rss/hot http://b.hatena.ne.jp/hotentry?mode=rss
本記事を執筆時点では、実行結果は以下のようになります。
<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
xmlns:content="http://purl.org/rss/1.0/modules/content/"
xmlns:itunes="http://www.itunes.com/dtds/podcast-1.0.dtd"
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/">
<channel>
<title>livedoor クリップ - 人気ページ と はてなブックマーク 最近の人気エントリー</title>
<link>http://clip.livedoor.com/rss/hot</link>
<description>livedoor クリップ - 人気ページ と はてなブックマーク 最近の人気エントリー</description>
08-06-23 22:52 $ ruby "test.rb" "http://clip.livedoor.com/rss/hot" "http://b.hatena.ne.jp/hotentry?mode=rss" | head -20
<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
xmlns:content="http://purl.org/rss/1.0/modules/content/"
xmlns:itunes="http://www.itunes.com/dtds/podcast-1.0.dtd"
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/">
<channel>
<title>livedoor クリップ - 人気ページ と はてなブックマーク 最近の人気エントリー</title>
<link>http://clip.livedoor.com/rss/hot</link>
<description>livedoor クリップ - 人気ページ と はてなブックマーク 最近の人気エントリー</description>
<item>
<title>Engineer25 すべてを楽しむ若きスーパーエンジニア達 第4回 cho45氏- ウェブキャリア</title>
<link>http://www.web-career.com/contents/engineer25/4.html</link>
<description></description>
<dc:subject>interview</dc:subject>
<dc:subject>ruby</dc:subject>
<dc:subject>javascript</dc:subject>
<dc:subject>program</dc:subject>
</item>
<item>
...中略...
</item>
</channel>
</rss>
解説
本サンプルプログラムは、大きく3段階の処理になっています。
第1段階(6行目から9行目)では、渡された引数を元に各ページにアクセスし、RSSを解析しています。
第2段階(11行目から20行目)では、rss_feeds内にRSSを分解したフィードの内容を登録しています。
今回は第一引数の出力内容を優先するので、順番を管理しやすいArrayに登録しました。そして、重複チェック用に、rss_urlsというArrayを作って、登録時にそこにurlを入れ、urlが既に登録されていないかチェックをしています。
第3段階目(25行目から34行目)では、全RSSの取得を完了した後で、makeでRSSを再生成して出力しています。
最後に――
今回のお題は主に自分が必要と感じるものを作ってみました。
パーサが標準のライブラリにあるので特に手間無く作れましたが、もうちょっと実用度を上げようとすると、サーバが落ちている場合や、引数が間違えている場合などの例外処理を組み込むのも良いと思います。
こんな風に作ってみたよという方が居られましたら、コメントやbuilderブログなどで教えていただきたいと思います。
- コメント(2件)
#1 someeda
- 2008/06/27 00:15:08
#2 tomita
- 2008/06/30 12:50:21
- 特集: Rubyでどう書く? (7件)
- ホワイトペーパー
- 企画特集
ストレージメディア特設サイト開設
ESBでIT投資の無駄を劇的に解消する
今注目の「サジェスト検索」−デモ掲載中
集積度も性能も、業界最高水準のブレードPC
御社のログ活用しませんか!?
セキュリティ&ユーザ事例【SIer Club】
中小企業のセキュリティリスクとは?
パンデミック対策特集
そのストレージで仮想化に対応できますか?
SOA、BPM、SaaS −今、企業に必要なこと
◆エン・ジャパン厳選求人☆毎週更新◆
仮想環境を実現するソリューション特集
ロリポップ!がリニューアル
インターネット上の悪意を未然に防ぐには?
【徹底対談】運用管理ツールの賢い使い方
- サーバー監視・運用のコストを削減するには
- ■ストレージ容量50%削減保証■
- サービス・ドリヴン・データセンター
- エンタープライズにおけるSUSEの強み
- 話題のタグ
Windows 7はLinuxへの切替が簡単:注目の仮想ディスクフォーマット「VHD」
iPhone OS 3.0で変わった「絵文字」
OSSのクラウド基盤「Eucalyptus」を使う(4)--インストール〜ノード構築
俳優経験者が指南する「人前で上手く話すためのティップス10選」
「うるまでるびペイント」登場:絵は上手下手ではなく制作過程に楽しみが
待てば回路の日和あり--「iPhone 3GS」発売、しかし――