これでFilterも作りやすくなるのかな...
例えば、はてなブックマークのフィードからShibuya.pmタグが付いてる物のOPMLを作るとか?(自身無さげ)
でもこれ、MIMEパターンをconfig.yamlに上手くめり込ませる方法ってないのかな...
指定する場合、「このURLに対しては変則的なxxxなMIMEで取りたい」って使いたいんだよね。
Index: lib/Plagger/Plugin/Subscription/Feed.pm
===================================================================
--- lib/Plagger/Plugin/Subscription/Feed.pm (revision 1959)
+++ lib/Plagger/Plugin/Subscription/Feed.pm (working copy)
@@ -17,7 +17,6 @@
sub load {
my ( $self, $context ) = @_;
- # TODO: Auto-Discovery, XML::Liberal
my $uri = URI->new( $self->conf->{url} )
or $context->error("config 'url' is missing");
@@ -30,6 +29,20 @@
my $content = Plagger::Util::load_uri($uri);
my $feed = eval { Plagger::FeedParser->parse(\$content) };
+ if unless($feed) {
+ use HTML::TokeParser;
+ my $parser = HTML::TokeParser->new(\$content);
+ while (my $token = $parser->get_tag("link")) {
+ my $attr = $token->[1];
+ if ($attr->{rel} eq 'alternate'
+ && ($attr->{type} eq 'application/rss+xml'
+ or $attr->{type} eq 'application/atom+xml') {
+ $uri = $attr->{href};
+ $feed = eval { Plagger::FeedParser->parse(\$content) };
+ last;
+ }
+ }
+ }
unless ($feed) {
$context->log( error => "Error loading feed $uri: $@" );
return;
こんな夜中に何やってんだか...
お腹が空いてきたので、モスバーガーのホームページからメニューをスクレイピングしてみる。
別に買いに行く訳じゃないけど...
思った以上に苦戦。苦戦の理由は「HTMLにIDやCLASSが殆んど振られておらず、XPathで抽出出来るパタンがない」こと。しょうがないのでまた無茶ぶりを発揮して、ノード階層をパタンとして使い、最小マッチのノードから欲しいノードへ上昇するというドロ臭いXPathを書いた。
パタンは、td要素を2つ持つtr要素で、かつそのtd要素内にはhref属性に"/menu/"という文字列を含んだa要素、しかもそのa要素は"pdf"という文字列を含んでいない。
結果、CSSセレクタは全く使わなかった(使えなかった?)。これじゃ、Web::Scraperのスライド資料の悪い例のままだ...
ま、取れたので良しとしよう。
mosburger-scraper.pl
#!/usr/local/bin/perl
use warnings;
use strict;
use Web::Scraper;
use YAML;
use URI;
my $uri = URI->new("http://www.mos.co.jp/menu/index.html");
my $mosburger = scraper {
process '//tr[count(td)=2]/td/a[contains(@href,"/menu/") and not(contains(@href,".pdf"))]/img/../../..',
'menus[]' => scraper {
process '/tr/td[1]/a', url => sub {URI->new_abs($_->attr('href'), $uri)->as_string;};
process '/tr/td[1]/a/img', title => '@alt';
process '/tr/td[1]/a/img', image => sub {URI->new_abs($_->attr('src'), $uri)->as_string;};
process '/tr/td[2]/a',
'perk' => scraper {
process '.', url => sub {URI->new_abs($_->attr('href'), $uri)->as_string;};
process 'img', title => '@alt';
};
};
result 'menus';
};
my $burgers = $mosburger->scrape($uri);
warn Dump $burgers;
---
- image: http://www.mos.co.jp/menu/img/ph_hamburger18.jpg
perk:
title: サウザン野菜バーガー ¥300
url: http://www.mos.co.jp/menu/hamburger/thousand/
title: サウザン野菜バーガー
url: http://www.mos.co.jp/menu/hamburger/thousand/
- image: http://www.mos.co.jp/menu/img/ph_hamburger19.jpg
perk:
title: [期間限定 10月中旬まで] シーザーサラダバーガー ¥300
url: http://www.mos.co.jp/menu/hamburger/seasar/
title: シーザーサラダバーガー
url: http://www.mos.co.jp/menu/hamburger/seasar/
...
補足情報(場合によってはセットメニュー)も一緒に取得出来ます。
あー。はらへった。
twitterのAPIでfriendsが100件しか取れなくなって久しいですが...
WWW::MechanizeとXPathでtwitterの全friendsを取得するサンプル作ってみました。
あまりやり過ぎると、オフィシャル側に怒られそうな気もしますが...
後の使い方は、適当で...
#!/usr/local/bin/perl
use warnings;
use strict;
use LWP::Simple;
use XML::Simple;
use WWW::Mechanize;
use HTML::TreeBuilder::XPath;
use HTML::Selector::XPath qw(selector_to_xpath);
use Data::Dumper;
my $username = 'your_username';
my $password = 'your_password';
my $m = WWW::Mechanize->new(timeout => 10);
$m->get('http://twitter.com/login');
$m->submit_form(
form_number => 1,
fields => {
username_or_email => $username,
password => $password,
},
button => 'commit',
);
my $xpath = selector_to_xpath('tr.vcard');
my @friends;
my $num_page = 1;
while (1) {
my $res = $m->get("http://twitter.com/friends/?page=$num_page");
my $encoding = $res->header('Content-Encoding');
my $content = $res->content;
$content = Compress::Zlib::memGunzip($content) if $encoding =~ /gzip/i;
$content = Compress::Zlib::uncompress($content) if $encoding =~ /deflate/i;
my $tree = HTML::TreeBuilder::XPath->new;
$tree->parse($content);
$tree->eof;
my @nodes = $tree->findnodes($xpath);
for my $tr (@nodes) {
push(@friends, {
nick => $tr->findnodes('td/strong/a')->[0]->as_text,
image => $tr->findvalue('td[@class="thumb"]//img/@src')->as_string,
name => $tr->findvalue('td[@class="thumb"]//img/@alt')->as_string,
description => $tr->findvalue('td/strong/a/@title')->as_string,
url => $tr->findvalue('td[@class="thumb"]/a/@href')->as_string,
});
}
$tree->delete;
@nodes or last;
$num_page++;
}
print Dumper @friends;
最近遊んでる物、ほとんどmiyagawa氏のものばっかだな...