ã¯ã¦ãªããã¯ãã¼ã¯, MM/Mmeo, del.icio.usã®RSSãã¾ã¨ãã¦åå¾ãã¦ã¿ã
アル厨ã§ã¯ãã¯ã¦ãªããã¯ãã¼ã¯ãMM/Memoãdel.icio.usããAlpha Geekãªçããã®ããã¯ãã¼ã¯ãåå¾ãã¦ãã¾ããã¿ã°æ å ±ã¯åãµã¼ãã¹ã§è¡¨è¨æ¹æ³ãéãã®ã§ããã®å·®ãæèããªãqouop::SBMãªãã¢ã¸ã¥ã¼ã«ãä½ã£ã¦å¯¾å¦ãã¾ãã(qouopã«æå³ã¯ç¡ãã§ããã¦ãã¼ã¯ãªã¢ã¸ã¥ã¼ã«åã«ããããã«ãqouop.dyndns.orgã§åä½ããã¦ãã®ã§ãã®ãããªååã«ãã¾ãã)ã
ã¤ã³ã¿ã¼ãã§ã¼ã¹ã¯ãããªæãã
use qouop::SBM; # $sbm_url(rssã®URL)ããã¤ã³ã¹ã¿ã³ã¹ä½æ $sbm = qouop::SBM->create($sbm_url); # ãã¼ã¿åå¾ $sbm->get(); # åã¢ã¤ãã æ å ±åå¾ my $items = $sbm->get_items(); foreach my $item (@{$items}) { # ããã¯ãã¼ã¯ã¿ã¤ãã«åå¾ my $title = $item->title; # ããã¯ãã¼ã¯èª¬æåå¾ my $description = $item->description; # ããã¯ãã¼ã¯ãããæ¥ä»åå¾ my $date = $item->date; foreach my $tag (@{$item->tag}) { # å$tagã«ã¤ãã¦ã®å¦ç } }
ã¤ã³ã¹ã¿ã³ã¹ä½æãnewã§ã¯ãªãcreateã«ãªã£ã¦ãã¾ãããããã¯ã¢ã¸ã¥ã¼ã«ä½¿ç¨è å´ã§åSBMãµã¼ãã¹ãæèããããªãã£ãã®ã§AbstractFactoryã£ã½ããã¦ããããã§ããcreateã«åSBMã®åºåRSSãæå®ããã¨ããã®RSSã«è¼ã£ã¦ããæ å ±ãåå¾ã§ããããã¿ã§ãã
ã§ã¯æ¬¡ã¯qouop::SBMã
package qouop::SBM; use strict; use warnings; use utf8; use LWP::UserAgent; use XML::Simple; use qouop::SBM::Delicious; use qouop::SBM::Hatena; use qouop::SBM::MM; use Encode; sub create { my ($self, $url) = @_; my $delicious_url = '^http://del.icio.us/rss/.*'; my $hatena_url = '^http://b.hatena.ne.jp/.*?/rss'; my $mm_url = '^http://1470.net/mm/mylist.html/.*?mode=xml'; return qouop::SBM::Delicious->_new($url) if ($url =~ /$delicious_url/); return qouop::SBM::Hatena->_new($url) if ($url =~ /$hatena_url/); return qouop::SBM::MM->_new($url) if ($url =~ /$mm_url/); return undef; } sub get { my $self = shift; my $content = $self->_get_resource($self->{url}); $content = $self->_convert_ltgt($content); my $parser = XML::Simple->new; my $rss = $parser->XMLin($content, ForceArray => 1); $self->{title} = $rss->{channel}->[0]->{title}->[0]; my @items; foreach my $item (@{$rss->{item}}) { my $i = qouop::SBM::Item->new; $i->title($item->{title}->[0]); $i->link($item->{link}->[0]); $i->description($item->{description}->[0]); $i->date($self->_localize_date($item->{'dc:date'}->[0])); $i->tag($self->_get_tags(\@{$item->{'dc:subject'}})); push @items, $i; } $self->{items} = \@items; } sub get_title {return shift->{title};} sub get_items {return shift->{items};} sub _new { my ($class, $url) = @_; my $self = { url => $url, title => undef, items => undef, }; bless $self, $class; return $self; } sub _get_resource { my ($self, $url) = @_; my $browser = LWP::UserAgent->new; $browser->agent('Crawler/0.1'); my $page = $browser->get($url) or die "cant get URL by LWP::UserAgent."; return $page->content; } sub _convert_ltgt { my ($self, $content) = @_; my ($enc_src) = ($content =~ /<\?xml .*? encoding="(.*?)"\s*\?>/); my $enc_dst = 'euc-jp'; print $enc_src; Encode::from_to($content, $enc_src, $enc_dst); my $lt = Encode::encode($enc_dst, '<'); my $gt = Encode::encode($enc_dst, '>'); $content =~ s/(.*)<title>(.*?)$lt(.*?)<\/title>(.*)/$1<title>$2<$3<\/title>$4/g; $content =~ s/(.*)<title>(.*?)$gt(.*?)<\/title>(.*)/$1<title>$2>$3<\/title>$4/g; $content =~ s/(.*)<description>(.*?)$lt(.*?)<\/description>(.*)/$1<description>$2<$3<\/description>$4/g; $content =~ s/(.*)<description>(.*?)$gt(.*?)<\/description>(.*)/$1<description>$2>$3<\/description>$4/g; $content =~ s/(.*)<dc:subject>(.*?)$lt(.*?)<\/dc:subject>(.*)/$1<dc:subject>$2<$3<\/dc:subject>$4/g; $content =~ s/(.*)<dc:subject>(.*?)$gt(.*?)<\/dc:subject>(.*)/$1<dc:subject>$2>$3<\/dc:subject>$4/g; Encode::from_to($content, $enc_dst, $enc_src); return $content; } sub _get_tags {die;}; sub _localize_date { my ($shift, $date) = @_; return $date; }; 1;
createé¢æ°ã¯id:jkondoããã®AbstractFactory例ã¿ããã«evalã§ã³ã¼ãæ¿å
¥ã®ã»ããã¹ãã¼ãã§ãããurlå¼æ°ãã§ãã¯ãå¿
è¦ã§çµå±qouop::SBMã§ã¯ãµãã¯ã©ã¹ãæèããå¿
è¦ããã£ãã®ã§ããã¿ã§æ¸ãã¦ã¾ãã
geté¢æ°ã§RSSã®ãã¦ã³ãã¼ãã解æãè¡ãã®ã§ãããXML::RSSã ã¨複数dc:subject読めなさそうな雰囲気ã ã£ãã®ã§ãããã§ã¯XML::Simpleã§å¯¾å¦ãã¦ã¾ã(éãã®TMTOWTDIãã¡ãªã¿ã«å½æã®ã¡ã¢ã¿ãã¨XML::RSSã®1001,1438è¡ç®è¾ºãããããããå¦çã¨èªèãã深追ãããã¨æ»ã£ã¦ããã«ã«æéããããããã ã£ãã®ã§ã¨ããããããããã¾ãã)ããã®å¦çå
ã§å¼ã°ãã¦ãã_get_localize_dateã¨_get_tagsã¯ãåSBMã¢ã¸ã¥ã¼ã«ã§å¿
è¦ã«å¿ãã¦ãªã¼ãã¼ã©ã¤ãããã¦ãã¾ãã
_convert_ltgté¢æ°ã¯RSS文字コード変換ã¨lt,gtã®å¤æã«ä½¿ç¨ãã¦ã¾ãããlt,gtå¤æã¯ä»ã¯å¿
è¦ãªãããã
package qouop::SBM::Item; use strict; use warnings; use base qw(Class::Accessor Class::Fields); use fields qw(title link description tag date); __PACKAGE__->mk_accessors(__PACKAGE__->show_fields('Public')); 1;
qouop::SBM::getå ã§è¨å®ããããåããã¯ãã¼ã¯ã¢ã¤ãã ã®æ å ±ãæã¤ãqouop::SBM::Itemã¢ã¸ã¥ã¼ã«ãããã§ã¯ãã¼ã¿ãæã£ã¦ããã ããªã®ã§Class::Accessorã¨Class::Fieldsã§æ¥½ãã¦ã¾ãã
package qouop::SBM::Hatena; use strict; use warnings; use utf8; use base qw(qouop::SBM); use qouop::SBM::Item; sub _get_tags { my ($self, $subject) = @_; return [@{$subject}]; } 1;
qouop::SBM::Hatenaã§ã¯_get_tagsã®ã¿ãªã¼ãã¼ã©ã¤ããã¦ãã¾ããã¨ã¯ãã£ã¦ããã¯ã¦ãªããã¯ãã¼ã¯ã®ã¿ã°æ å ±ã¯è¤æ°dc:subjectã§åå¾ã§ããã®ã§qouop::SBMãã渡ãããdc:subjectãªãã¡ã¬ã³ã¹ããã®ã¾ã¾è¿ãã¦ããã ãã§ãã
package qouop::SBM::MM; use strict; use warnings; use utf8; use base qw(qouop::SBM); use qouop::SBM::Item; sub _get_tags { my ($self, $subject) = @_; my $token = ', '; my $tags = $subject->[0]; if ($tags) { if ($tags =~ /$token/) { return split($token, $tags); } else { return [$tags]; } } else { return undef; } } 1;
MM/Memoã¯ä¸ã¤ã®dc:subjectå ã«", "åºåãã§ã¿ã°æ å ±ãå ¥ã£ã¦ããã®ã§ãä¸è¨ã®ãããªå¦çã«ãªã£ã¦ãã¾ãã
package qouop::SBM::Delicious; use strict; use warnings; use utf8; use base qw(qouop::SBM); use qouop::SBM::Item; use DateTime; use DateTime::Format::W3CDTF; sub _get_tags { my ($self, $subject) = @_; my $token = ' '; my $tags = $subject->[0]; if ($tags) { if ($tags =~ /$token/) { return split($token, $tags); } else { return [$tags]; } } else { return undef; } } sub _localize_date { my ($shift, $date) = @_; my $f = DateTime::Format::W3CDTF->new; my $dt = $f->parse_datetime($date); $dt->set_time_zone('Asia/Tokyo'); my $ret = $dt.'+09:00'; return $ret; }; 1;
del.icio.usã¯ä¸ã¤ã®dc:subjectã«ã¹ãã¼ã¹åºåãã§ã¿ã°æ å ±ãå ¥ã£ã¦ããã®ã§ãä¸è¨ã®ãããª_get_tagså¦çã¨ãªã£ã¦ãã¾ããdel.icio.usã ãã¯æå»æ å ±ã9æéããã¦ããã®ã§ãDateTime::Format::W3CDTFã§æå»æ å ±ãåããã¦ãã¾ãã
iTMSé¨ãã§ãã®ã¢ã¸ã¥ã¼ã«ã«ã¤ãã¦æ¸ããã¨ãå¿ãã¦ããã®ã§ããããPerlプログラマのレベル10 - Perlプログラミング救命病棟よりãã§æãåºããã®ã§ä»é æ¸ãã¾ããããã®ã¢ã¸ã¥ã¼ã«æ¸ãå§ããããã¯perlã§ãã©ã¤ãã¼ãã¡ã½ããã®å®ç¾©æ¹æ³ããããã¾ããã§ãã(ã¨ããããå é ã«_ãã¤ããã®ãæé»ã®äºè§£ããªãã§ãããï¼)ãå¤åæ£è¦è¡¨ç¾ã®ä½¿ãæ¹ã¨ãã¢ã¸ã¥ã¼ã«è¨è¨ã§ã¬ãã«7以ä¸ã®äººãã¡ã¨å·®ãåºããã§ããããã