- ランプの中身(Ruby on Railsのシステム開発)
- ランプの中身(Ruby on Railsのシステム開発)では、株式会社ケイビーエムジェイのRuby on Railsエンジニアが蓄積したノウハウを公開しています。Ruby on Railに関する技術解説や実践的なノウハウなど、開発現場の技術に則したコンテンツを随時追加していきます。 初心者の方でもわかりやすい技術解説を心がけています。リクエスト、ご質問も受け付けいますので、お気軽にコメントを記述して下さい。
< Rubyでどう書く?:Rubyで特定UR... | メイン | Rubyでどう書く?:RubyでWord... >
-
- 2008.06.25
Rubyでどう書く?:重複したRSSをまとめる
KBMJがZDnetで連載している記事を紹介します。コメントなどありましたらそちらでお願いします。
Rubyでどう書く?:重複したRSSをまとめる 高瀬裕一(KBMJ)
「ネットの話題を追いかけるために、はてブのホッテントリや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 = rss_urls = []
4 title=""
5
6 ARGV.each do | rss_url |
7 open(rss_url) do | http |
8 response = http.read
9 rss_results = RSS::Parser.parse(response, false)
10
11 if rss_results && rss_results.channel && rss_results.channel.title
12 title += " と " if title.size > 0
13 title += rss_results.channel.title
14 end
15
16 rss_results.items.each do | item |
17 unless rss_urls.include? item.link
18 rss_urls << item.link
19 rss_feeds << item
20 end
21 end
22 end
23 end
24
25 rss = RSS::Maker.make("2.0") do | writer |
26 writer.channel.title = title || ""
27 writer.channel.link = rss_urls[0] || ""
28 writer.channel.description = title || ""
29 rss_feeds.each do | feed |
30 feed.setup_maker(writer)
31 end
32 end
33
34 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ブログなどで教えていただきたいと思います。
トラックバック URL
この記事にコメントする
TOPICS
2008/08/14
「ZD Net Builder」の連載記事です。第七回は「Rubyでどう書く?:RubyCocoa+Core Animationでお手軽アニメーション」が掲載されました。
2008/08/06
「ZD Net Builder」の連載記事です。第六回は「Rubyでどう書く?特別編:Matzからのお題」が掲載されました。
2008/07/29
「アットマーク・アイティ」にケータイWebアプリ開発、9つの注意点が掲載されました。
2008/07/11
「ZD Net Builder」の連載記事です。第五回は「Rubyでどう書く?:RubyでWord文書を作成する」が掲載されました。
gotoの最新記事一覧
カテゴリ
全体のRoR最新ブログ一覧
- Rubyの例外処理
- Rubyでどう書く?:RubyCocoa+Core Animationでお手軽アニメーション
- Rubyでどう書く?特別編:Matzからのお題
- ntpをインストールする
- Rak(grepの検索結果を見やすくする方法)
- ruby on railsのActionControllerにモジュールでbefore_filterを実装する方法
- postfixのaliasでメールを転送してみよう。
- カーネルの再構築
- splitで文字列を分割してみよう。
- ウォームスタンバイの復旧手順
- nfkで文字コードを変換してみよう。
- RDBMSでトランザクション処理をしてみよう。
- apacheでhttpsからhttpsへのリダイレクト方法
- SSL更新時のエラー 改行コードの注意点 for mac
- bondingでNICを冗長化しよう。
- Net/HTTPで圧縮ファイルをダウンロードしよう。
- PostgreSQL8.3でウォームスタンバイの設定
- capistranoでmongrel,apache,rsync
- Cybozuのスケジュールをmobileme経由でiPhone 3Gに取り込む
- 今週のRuby on Rails最新情報
- Rubyでどう書く?:RubyでWord文書を作成する
- iPhoneを確保しました
- Edge Railsの最新情報
- Rubyのセキュリティ脆弱性
- mysqlでレコードの中身を一括置換する方法
- 同じappでDBを使い分ける
- Rubyでどう書く?:重複したRSSをまとめる
- TABLEに直接データを入れる便利な方法
- 社内SNSをiPhoneで快適に見るためのCSSを書いてみた
- phpmyadminをセキュアにアクセスする方法
- Rubyプログラムの組み方から、Exeファイルの作成まで
- Ruby、Railsインストール for MacOSX
- will_paginageを使ってみた
- dmgファイルの作り方
- PHP携帯電話の機種情報取得
- Rubyでどう書く?:Rubyで特定URLの画像パス一覧を表示する
- リファラでアクセス制限をしてみた。
- 奇妙な演算子
- RJSを用いて、日付プルダウンメニューを書き換える (2
- railsの実行モードの設定 RAILS_ENV
- postgresでのユーザ権限付与(psql, grant)
- ドロップダウンに簡単にオートコンプリート機能を追加する方法
- Vimの自動補完
- IE6 以前で float に指定した margin が 2 倍になる現象を解消する
- サーバ監視ソフトウェア「ganglia」を使ってみる
- 監視ツールcactiについて
- Rubyでどう書く?:RubyでPDF履歴書を作成する
- グラフを作ってみるか!?
- clearfixでfloat解除
- SELinux無効にしてみる
- Rubyのソースコードから HTML Helpを生成してみよう!
- IEでダイジェスト認証をかけるとエラーになった。
- muninのインストール 〜監視ツールって〜
- Rubyでどう書く?:連続した数列を範囲形式にまとめたい
- RJSを用いて、日付プルダウンメニューを書き換える
- Passenger (mod_rails for apache)での色んな設定値について調べてみた
- docomo の罠
- ローカルで動画変換をする方法
- MacOSにpostgreSQL 8.3をインストール
- Postgres8_3⇔8_1の性能比較してみました
- rake db:migrate すると undefined method `last' for {}:Hash と出る
- ケータイWebサイトに携わっている方へ
- MySQL最大バッファサイズの設定
- railsのand/orを使った機能
- Railsライクなフレームワーク「CakePHP」②
- エラー表示で意図しない改行を解消する−fieldWithErrors、ActionView::Base、field_error_proc
- [mysqlのベンチマーク]MyBenchの設定
- Rubyのコマンドライン引数と環境変数について(初心者向け)
- Rubyを使ってPaSoRi経由でSuicaの乗車履歴を取得し、GoogleMapsやGoogleEarthで表示する
- 簡単&便利 Capistranoのススメ (導入編)
- Rails的コメントアウト
- 使えるvalidate一覧
- せっかくなので、Thin を使って実践
- Xenを用いてCentOS上に仮想CentOSを2つインストールする
- aptanaでrailsをデバッグ実行する
- empty?とblank?の違いって?
- ローカルでコマンドを打つとアスタリスクで囲まれたエラーが出る
- rubyの便利ツールirbをカスタマイズしてみた
- 実行モード "environment"設定の基本
- JRubyを触ってみた
- mongrelとの戦い〜503エラー?mongrelが死んだってことさ…
- sshでrootログインの禁止
- database.ymlの設定方法
- Railsライクなフレームワーク「CakePHP」①
- Rails導入でRuby標準クラスへ追加される関数達(String編)
- Rubyのマニュアルを手軽に参照する方法
- railsで画像などファイルをアップロードする方法
- 遠隔地のチョロQを操縦する方法 with JavaScript, AJAX, Rails, Gainer, Webカメラ, and USTREAM.TV
- Ruby on Railsで作られたradMineのカスタマイズ1 ~インストール編~
- MacBook AirのレビューとLet's noteとの比較
- Rails プラグイン : CSS Graphsの使い方(そしてちょっとだけ改造)
- Railsの開発でscreenを使う理由
- ActiveRecordのconditionsを綺麗に書くTips2つ
- [Rails 2.0]起動時のファイルの読み込みの順番がわかった!
- RailsのActionMailer(Tmail)でドットの連続などのRFC違反している携帯メールアドレスに対応する
- スパムを消して消して、もう消しまくって こうなりました。
- Ruby on Railsでacts_as_paranoidを使い倒す
- fastladderをrailroadで図を作ってみる。
- [書評] 他言語開発経験者でも、初心者でも、本屋で「チラ見」して確認してみよう
- ヘルパーメソッド
- Ruby標準csv遅い
- Linux2.6系の脆弱性でroot権限奪ってみた
- railsで開発したダイエットサイトとそのソースコード
- fastladderを試してみました ~rails2.0~
- HeartBeatの設定
- Railsの手動インストール
- Railsで「Lost connection to MySQL server during query」に遭遇した場合の対策
- RadiantCMSのインストール(2)
- Linuxとかのbashで使えるショートカットキーをまとめた一覧
- 長い文字列をカットして表示するプログラム
- SLこまんどの設定
- Rails プラグイン : Rails Widgets >Tabnavの使い方
- Scaffoldはどこからくるの? 後編
- ローカルメールサーバーでRailsでのメール受信のテストを便利に
- HTMLエスケープ
- aptanaのインストールと使い方について
- railroadを用いたER図作成
- RailsでAmazon APIを利用する
- ちょっとしたスペルミスなどで、時間を無駄にした経験があるなら ( カラー表示で編集しやすく )
- ちょー入門、Webサーバ構築で知ってて損をしない用語(2)
- Ruby on Rails ってなになに?
- 最近!流行りの、「Ruby」 知ってますか?
- RubyGems って単語よく出てきますよね?
- CentOS5とaptanaを使ったWindows開発環境 1
- gemコマンドの紹介
- ちょー入門、Webサーバ構築で知ってて損をしない用語(1)
- RadiantCMSのインストール(1)
- RubyでActiveRecordを使わないでDBに接続する方法
- Railsのキャッシュ機能を用いて動的ページを静的ページにする方法を紹介
- Rails 2.0のセキュリティ面の変更点
- DRBDのインストール
- Rails プラグイン : ColumnCommentsの使い方
- Scaffoldはどこからくるの? 前編
- RMagickの使い方
- Ruby on Rails インストール for Windows
プロフィール
- goto
-
23 歳
- 毎週KBMJでは、"ZDnet"にRubyの記事を連載しています。
ここでは、その記事を紹介します。




