« Operaをアップデート | メイン | 今日も勝った。次も勝つぞぉ。 »

PerlでRSSの処理のベンチマーク

NDO::WeblogさんのPerl で XML の処理はどれが速いかベンチで、正規表現、XML::Simple、XML::RSS、XML::LibXMLの4つで、RSSの中から、linkを抜き出すベンチの記事が公開されていますが、
もうすこし、RSSの中から情報を抜き出して、Perlで使いやすいようにしていったらどうなるか試してみた。
ちょっとさぼって、XML::RSSとXML::LibXMLだけ

まず結果から

# perl libxmlrss.pl index.rdf 
Benchmark: timing 100 iterations of XML::LibXML, XML::RSS...
XML::LibXML:  5 wallclock secs ( 4.49 usr +  0.02 sys =  4.51 CPU) @ 22.17/s (n=100)
  XML::RSS: 24 wallclock secs (24.40 usr +  0.01 sys = 24.41 CPU) @  4.10/s (n=100)

やはり、XML::RSSはXML::LibXMLに比べて遅いです。
XPathの書き方がこれでいいのかどうかわからないのでもうすこし改善できるところなどありそうです。

スクリプトはNDO::Weblogさんのを参考にして書きました
XML::LibXMLを使った方は、RSS1.0でencodeモジュールを使用している時のみ対応です。
実際XML::LibXMLを使うには処理を分ける必要があると思います。

#!/usr/bin/perl

use strict;
use XML::LibXML;
use XML::RSS;
use IO::File;
use Benchmark;

my $rss_file = shift or die "usage $0";
my $fh = IO::File->new($rss_file) or die "cannot open $rss_file: $!";
my $content = join("",$fh->getlines);
$fh->close;

Benchmark::timethese(100, {
    'XML::RSS' =>\&with_xml_rss,
    'XML::LibXML' => \&with_xml_libxml,
});

sub with_xml_rss{
	my %rss;
	my $rss = XML::RSS->new;
	$rss->add_module(
		prefix=>"content",
		uri=>"http://purl.org/rss/1.0/modules/content/"
	);
	$rss->parse($content);
	
	my $channel = $rss->channel;
	$rss{title} = $channel->{title};
	$rss{link} = $channel->{link};
	$rss{date} = $channel->{dc}->{date};
	my @items;
	foreach my $item (@{$rss->{items}}){
		my %item;	
		$item{title}=$item->{title};
		$item{link}=$item->{link};
		$item{description}=$item->{description};
		$item{encoded}=$item->{content}->{encoded};
		$item{subject}=$item->{dc}->{subject};
		$item{creator}=$item->{dc}->{creator};
		$item{date}=$item->{dc}->{date};
		push(@items,\%item);
	}
	$rss{items}=\@items;
}

sub with_xml_libxml{
	my %rss;
	my $parser = XML::LibXML->new;
	my $doc = $parser->parse_string($content);

	$rss{title} = $doc->findvalue("//*[local-name()='channel']/*[local-name()='title']/text()");
	$rss{link} =  $doc->findvalue("//*[local-name()='channel']/*[local-name()='link']/text()");
	$rss{date} = $doc->findvalue("//*[local-name()='channel']/dc:date/text()");

	my @nodes = $doc->findnodes(
		"//*[local-name()='item']"
	);
	my @items;
	for my $node (@nodes){
		my %item;
		$item{title}=$node->findvalue("*[local-name()='title']/text()");
		$item{link}=$node->findvalue("*[local-name()='link']/text()");
		$item{description}=$node->findvalue("*[local-name()='description']/text()");
		$item{encoded}=$node->findvalue("./content:encoded/text()");
		$item{subject}=$node->findvalue("./dc:subject/text()");
		$item{creator}=$node->findvalue("./dc:creator/text()");
		$item{date}=$node->findvalue("./dc:date/text()");
		push(@items,\%item);
	}
	
	$rss{items}=\@items;
}

トラックバック

この一覧は、次のエントリーを参照しています: PerlでRSSの処理のベンチマーク:

» XML::LibXMLを用いてRSSファイルからデータをゲットする方法 from TSJ付゛録゛
 今日は1日、TSJのPerlスクリプトの改造ばっかりやっていました(←バカ)。  登録サイトでRSSのURIを指定していれば、RSSファイルをゲットしてサマリを表示させるというものですが、これがなかなかのくせ者でした。  最初、「XML::RSS」モジュールを使ってRSSをゲッ... [詳しくはこちら]

» XML::LibXMLを用いて様々なヴァージョンのRSSファイルからデータをゲットする方法 from TSJ付゛録゛
 嗚呼、もう夜中の1時過ぎだ(ToT)。  と言う訳で、昨日かぜぶろ様からご教示いただいた方法を元に、いろいろ試行錯誤してようやくヴァージョン0.91のRSSから情報を取得することに成功しました。  証拠。「TSJ Directory」で、キーワード「内房線」を指定して検索した... [詳しくはこちら]

» XML:RAI XML::RSSとの比較 from blog.nomadscafe.jp
XML::RAIというRSS Parser モジュールがあります。 The RSS Abstraction Interface, or RAI (said "ray"), provides an object-oriented interface to XML::RSS::Parser trees that abstracts the user from handling namespaces, overlapping and alternate tag mappings... [詳しくはこちら]

» はてなブックマークの RSS を parse してベンチマークをとってみた from 金子健介の livedoor Blog
はてなブックマークの RSS をパースしてみようと思って XML::Liberal というか XML::LibXML と格闘したり XML::RSS::L... [詳しくはこちら]