[Home] [Kuri] [Sysad] [Internet?] [Blog] [Java] [Windows] [Download] [Profile] [Flash] [+]

Perl で RSS を扱ってみた

今はやりの RSS を、Perl で扱ってみました。


目次


1. 環境

以下は、Vine Linux 2.5 と FreeBSD 4.1 上で試しました。
ここの例では、Perl の XML-RSS と libwww を使っています。 これらが入っていれば、他の OS でも動くのではないかと思います。

Vine Linux 2.5 では、動作させるために以下をインストールしました。

FreeBSD 4.1 では、以下をインストールしました。


2. RSS とは

RDF Site Summary あるいは Rich Site Summary (あるいは…)の略です。
そのサイトの概要をメタデータとして XML で記述したもの…というよりも、 XML のフォーマット自体のことのようです。

で、RSS の要素ですが、大きく分けて、channel, item, image, textinput からなります。

channel 要素には、タイトルや概要、URI などの基本情報が記述されています。
item 要素には、リソースの内容が記述されています。 channel の items で指定した分記述する必要があります。
image 要素には、ロゴなどの画像に関する情報が記述されています。 channel で指定した場合に必要となります。
textinput 要素には、検索などのフォームに関する情報が記述されています。 channel で指定した場合に必要となります。

image 要素、textinput 要素は、必須ではないです。
…詳しくは、メジャーな検索サイトで、RSS で検索してみてください。


3. RSS を読む

とりあえず作った Perl スクリプトは、以下の通りです。

#!/usr/bin/perl
use LWP::Simple;
use XML::RSS;

if($#ARGV != 0) {
	print STDERR "Usage: ./get.pl URL\n";
	exit 1;
}

$url = shift;
$dat = get($url);
$rss = new XML::RSS;
$rss->parse($dat);

$chan = $rss->{'channel'};
print "$chan->{'title'} : $chan->{'link'}\n\n";
if($chan->{'description'}) {
	print "$chan->{'description'}\n\n";
}
foreach $item (@{$rss->{'items'}}) {
	next unless defined($item->{'title'}) && defined($item->{'link'});
	print "  $item->{'link'}\n\t$item->{'title'}\n";
}

LWP::Simple は、引数で指定された URL から RSS なファイルをとってくるためだけに使用しています。 11行目の get がそれです。
12行目の new でオブジェクトを作り、 13行目で、先ほど得た RSS ファイルの内容を解析させます。
そして 15行目で、channel 要素オブジェクト(?)を得て、16〜18行でその内容を出力します。
あとは、item 要素1つ1つの内容を出力しているだけです。

では、実際に動かしてみます。
CNET Japan の RSS News FeedCNET Japan で試してみます。
文字コードが UTF-8 ですので、iconv で EUC に変換してから見ます。

  % ./get.pl http://japan.cnet.com/info/rss/index.rdf | iconv -f UTF-8 -t EUCJP
  CNET Japan : http://japan.cnet.com/

    http://japan.cnet.com/news/ent/story/0,2000047623,20061640,00.htm?ref=rss
          米マイクロソフト、開発者向けカンファレンス開幕--注目の「Longhorn」初披露
    http://japan.cnet.com/news/tech/story/0,2000047674,20061639,00.htm?ref=rss
          米デル、MP3プレーヤー「Dell DJ」を発表
    http://japan.cnet.com/news/ebiz/story/0,2000047658,20061635,00.htm?ref=rss
          「本が売れなくなる」:米アマゾンの全頁検索に米作家団体が反発
    ...後略


4. RSS を作る

RSS にはいくつかバージョンがあるようですが、XML-RSS は、 0.9, 0.91, 1.0, 2.0 に対応しているようです。
ここでは、1.0 の RSS を作成するスクリプトを作ってみました。

#!/usr/bin/perl
use XML::RSS;

my $rss = new XML::RSS (version => '1.0');

$rss->channel(title => 'Kuri Nikki',
	link => 'http://www.usupi.org/kuri',
	language => 'ja',
	description => '毎日栗の絵を書いているのだよ。',
	copyright => 'Copyright (c) 2001-2003,  USUDA Hisashi',
	managingEditor => 'kuri@usupi.org',
	dc => {
		language => 'ja',
		rights => 'Copyright (c) 2003 USUDA Hisashi',
		date => '2003-09-09T12:00:00+09:00',
	},
	webMaster => 'usu@usupi.org');

$rss->add_item(title => '2003/09/09',
	link => 'http://www.hoteagle.org/s/servlet/dcontent?user=kuri&date=2003-09-09',
	description => '2003/09/09',
	dc => {
		date => '2003-09-09T12:03:12+09:00',
	});
$rss->add_item(title => '2003/09/10',
	link => 'http://www.hoteagle.org/s/servlet/dcontent?user=kuri&date=2003-09-10',
	description => '2003/09/10',
	dc => {
		date => '2003-09-10T19:43:21+09:00',
	});

print $rss->as_string;

最初に new でオブジェクトを生成しています。
次に、channel で channel 要素を作っています。
そして、add_item で各 item 要素を作っています。
最後に、as_string で文字列に変換したものを、print しています。

item 要素の情報がスクリプトに埋め込まれていますが、 DB から更新情報を入手して add_item するようにしてしまえば、 自動化できて楽になれそうです。(してないけど…)

出力結果は、以下のようになります。

<?xml version="1.0" encoding="UTF-8"?>

<rdf:RDF
 xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
 xmlns="http://purl.org/rss/1.0/"
 xmlns:dc="http://purl.org/dc/elements/1.1/"
 xmlns:taxo="http://purl.org/rss/1.0/modules/taxonomy/"
 xmlns:admin="http://webns.net/mvcb/"
 xmlns:syn="http://purl.org/rss/1.0/modules/syndication/"
>

<channel rdf:about="http://www.usupi.org/kuri">
<title>Kuri Nikki</title>
<link>http://www.usupi.org/kuri</link>
<description>毎日栗の絵を書いているのだよ。</description>
<dc:language>ja</dc:language>
<dc:rights>Copyright (c) 2003 USUDA Hisashi</dc:rights>
<dc:date>2003-09-09T12:00:00+09:00</dc:date>
<dc:publisher>kuri@usupi.org</dc:publisher>
<dc:creator>usu@usupi.org</dc:creator>
<items>
 <rdf:Seq>
  <rdf:li rdf:resource="http://www.hoteagle.org/s/servlet/dcontent?user=kuri&date=2003-09-09" />
  <rdf:li rdf:resource="http://www.hoteagle.org/s/servlet/dcontent?user=kuri&date=2003-09-10" />
 </rdf:Seq>
</items>
</channel>

<item rdf:about="http://www.hoteagle.org/s/servlet/dcontent?user=kuri&date=2003-09-09">
<title>2003/09/09</title>
<link>http://www.hoteagle.org/s/servlet/dcontent?user=kuri&date=2003-09-09</link>
<description>2003/09/09</description>
<dc:date>2003-09-09T12:03:12+09:00</dc:date>
</item>

<item rdf:about="http://www.hoteagle.org/s/servlet/dcontent?user=kuri&date=2003-09-10">
<title>2003/09/10</title>
<link>http://www.hoteagle.org/s/servlet/dcontent?user=kuri&date=2003-09-10</link>
<description>2003/09/10</description>
<dc:date>2003-09-10T19:43:21+09:00</dc:date>
</item>

</rdf:RDF>

ただ、このままですと、encoding が UTF-8 のままで出力されてしまいます。
ですので、以下のように、iconv で変換してやりました。

  % ./kuriate.pl | iconv -f EUCJP -t UTF-8 > kuri.rdf

あるいは、new するときに、以下のように encoding を指定する方法もあります。
ただ、UTF-8 しか解釈できないものもありますので、 UTF-8 のままが無難ではないかと思われます。
# ちなみに、使っている XML-Parser は、 x-euc-jp-jisx0221 という長ったらしい名前でないと受け付けてくれませんでした。

my $rss = new XML::RSS (version => '1.0', encoding => 'euc-jp');

Powered by Apache PostgreSQL Usupi Logo Kuri Logo
[Home] [Kuri] [Sysad] [Internet?] [Blog] [Java] [Windows] [Download] [Profile] [Flash] [-]
usu@usupi.org Last modified : Thu Oct 30 23:34:19 2003