Published on Blog Developer's Cookbook.
Printer friendly version of http://blog.bulknews.net/cookbook/blosxom/rss/blogrolling2rss.html.
BlogRolling を利用して RSS 巡回先を管理
by miyagawa at Sat, 25 Oct 2003 23:05
RSS は Aggregator で読むだけではなく、様々な使用方法があります。お気に入りの RSS リスト(巡回先) が肥大してくると、この管理もなかなか大変です。今回は BlogRolling というサービスを使用して、RSS 巡回先の管理を行ってみます。
BlogRolling
RSS Aggregator に登録した Blog サイトの巡回先が肥大化してくると、以下のような問題が生じます。
- Aggregator のソフトを移行するときに登録しなおし
- 自宅の PC と職場の PC で不整合が発生
これは Web ブラウザの Bookmark を自宅と職場で同期したいという要望に非常によく似ています。オンラインでブックマーク管理できる各種オンラインブックマークサービスが登場したのと同様に(*1)、自分の巡回する Blog サイトのリストを Web 上で管理できるサービスが、BlogRolling です。
BlogRolling は、Weblogs.Com の changes.xml に掲載されている更新情報をもとにして(*2)、自分の巡回する Blog リストを更新順に並べかえてくれるサービスです。BlogRolling の URL リストは JavaScript で HTML 出力する機能を持っているため、巡回リストを更新時間順に(*3)ソートして、自分の Blog の SideBar などに張りつけることができます。ちょうど はてなダイアリー のサイドバーに はてなアンテナ のアンテナを張りつけるのに似ていますね。
こうして巡回先リストを Web 上の BlogRolling に保持しておくことで、
- 自宅の PC
- 職場の PC
- Blog サイト上のサイドバー
のように各所で利用している「巡回リスト」が BlogRolling で一括管理できるようになります。
BlogRolling はブラウザから 1-Click で登録する Bookmarklet や "BlogRoll Me" (*4) などの簡易登録インタフェースも用意しているため、「お、このサイトいいな」と思った際に、すぐに追加できるのも便利なところです。
BlogRolling に登録したサイトの RSS 一覧を取得
BlogRolling の巡回結果は JavaScript 以外にも RSS や OPML(*5) での出力もサポートしています。RSS での出力は List 1 のようになっており、更新時刻順に Blog サイトのタイトルや URL が item の要素に出力されています。
このように、BlogRolling で管理した巡回先マスタ(RSS)から Blog リストを抽出して、RSS の更新情報をメールで送信 などのアプリケーションに渡すようにすれば、Web で管理した Blog リストについて、メーラで更新情報を取得できるという大層なアプリケーションが簡単に作成できます。
注意すべきは、BlogRolling の出力する RSS には、サイト毎の RSS の URL は含まれていないことです。RSS Auto Discovery を利用して RSS のリストを作成してあげればよいでしょう。
サンプルコード
BlogRolling の BlogRoll (*6) から RSS リストを抽出するスクリプトは List 2 のようになります。
use HTML::RSSAutodiscovery;
use LWP::Simple;
use Storable;
use XML::RSS;
使用するモジュールを use します。データのキャッシュに Storable、また RSS Auto Discovery 用に HTML::RSSAutodiscovery を使用します。
our $CacheFile = "rss.cache";
our $BlogRollingId = "fd16d26c9ad1029c21a48955b8c19731";
設定項目を our で格納します。ここでは URL から RSS へのマッピングを保存するキャッシュファイルのパス、また BlogRolling のアカウント ID (*7) を設定します。
my $cache = eval { Storable::retrieve($CacheFile) } || {};
Storable 形式で保存されたキャッシュをロードします。ファイルがない場合は例外が投げられるので, eval でトラップして初期化します。
my $url = "http://rpc.blogrolling.com/rss.php?r=$BlogRollingId";
my $xml = LWP::Simple::get($url);
RSS を出力する RPC に、自分の BlogRolling ID を付加して RSS ファイルを HTTP GET します。
my $rss = XML::RSS->new();
$rss->parse($xml);
for my $item (@{$rss->{items}}) {
$cache->{$item->{link}} ||= discover_rss($item->{link}) or next;
print $cache->{$item->{link}}, "\n";
}
いつものように、XML::RSS でパースして、各 item について処理します。item の link に Blog の URL が格納されています。キャッシュを lookup して、存在しなければ discover_rss で、その URL への RSS を探します。見つかれば標準出力に print します。
sub discover_rss {
my $url = shift;
my $discovery = HTML::RSSAutodiscovery->new();
my $rss = $discovery->parse($url);
unless (@$rss) {
warn "no RSS found for $url\n";
return;
}
return $rss->[0]->{href};
}
今回は HTML::RSSAutodiscovery を使用して RSS の自動探索を行っています。マッチした結果は配列リファレンスで取得できます。自動探索に失敗すると要素が 0個の配列となるため、warning を出力し return します。マッチした場合には 1つめのエントリの href 要素を RSS の URL として返します。
Storable::nstore($cache => $CacheFile);
最後にキャッシュした結果をファイルに書き出します。これによって1つの URL に対して複数回 RSS の自動探索を行うことが防げます(*8)。
実行例
コマンドラインで実行すれば、RSS の URL 一覧が STDOUT に出力されます。
% ./blogrolling2rss.pl
http://www2u.biglobe.ne.jp/%7Ekyo-n/blog/blosxom.cgi/index.rss
http://blog.bulknews.net/cookbook/blosxom/index.rss10
http://blog.bulknews.net/mt/index.rdf
http://shibuya.pm.org/blosxom/index.rss10
http://naoya.dyndns.org/~naoya/mt/index.rdf
この結果をファイルに格納するようにして、
% ./blogrolling2rss.pl > blogrolling.txt
このファイル内の RSS を rss2email に食わせれば、前述したようなメールによる Blog サイト Aggregator の出来上がりです。しかも巡回先リストの管理画面つき (BlogRolling のサイトで行えます)です。
See Also
- RssRolling は、BlogRolling の巡回リストから RSS を抽出し、取得したエントリをさらにマージして HTML や RSS 等にして配布しているサービスです。
Listings
<?xml version="1.0"?>
<!-- RSS generation done by 'Blogrolling.com'-->
<rss version="0.92">
<channel>
<title>blog.bulknews.net</title>
<link>blog.bulknews.net</link>
<description>Blogrolling.com RSS Feed</description>
<lastBuildDate>Thu, 23 Oct 2003 11:52:08 GMT</lastBuildDate>
<docs>http://www.blogrolling.com/</docs>
<webMaster>rss@blogrolling.com (Blogrolling RSS Generator)</webMaster>
<item>
<title>HAIL 2 U !! - Weblog</title>
<link>http://www2u.biglobe.ne.jp/%7Ekyo-n/blog/blosxom.cgi</link>
<description>Last updated: 12:08:48 GMT on Thursday, October 23</description>
</item>
<item>
<title>Blog Developer's Cookbook</title>
<link>http://blog.bulknews.net/cookbook/blosxom</link>
<description>http://blog.bulknews.net/cookbook/blosxom</description>
</item>
<item>
<title>blog.bulknews.net</title>
<link>http://blog.bulknews.net/mt/</link>
<description>http://blog.bulknews.net/mt/</description>
</item>
<item>
<title>Shibuya Perl Mongers</title>
<link>http://shibuya.pm.org/</link>
<description>http://shibuya.pm.org/</description>
</item>
<item>
<title>NDO::Weblog</title>
<link>http://naoya.dyndns.org/</link>
<description>http://naoya.dyndns.org/</description>
</item>
</channel>
</rss>
#!/usr/local/bin/perl -w
# blogrolling2rss - extract RSS feeds from BlogRolling URL list
use strict;
use HTML::RSSAutodiscovery;
use LWP::Simple;
use Storable;
use XML::RSS;
our $CacheFile = "rss.cache";
our $BlogRollingId = "fd16d26c9ad1029c21a48955b8c19731";
my $cache = eval { Storable::retrieve($CacheFile) } || {};
my $url = "http://rpc.blogrolling.com/rss.php?r=$BlogRollingId";
my $xml = LWP::Simple::get($url);
my $rss = XML::RSS->new();
$rss->parse($xml);
for my $item (@{$rss->{items}}) {
$cache->{$item->{link}} ||= discover_rss($item->{link}) or next;
print $cache->{$item->{link}}, "\n";
}
Storable::nstore($cache => $CacheFile);
sub discover_rss {
my $url = shift;
my $discovery = HTML::RSSAutodiscovery->new();
my $rss = $discovery->parse($url);
unless (@$rss) {
warn "no RSS found for $url\n";
return;
}
return $rss->[0]->{href};
}
Copyright©2002-2003 Tatsuhiko Miyagawa