2008/01/31


これで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;
Posted at by




muumoo.jpPlaggerで取得したGoogleブックマークのフィードを整えるFilter:GoogleBookmarksFeedを書いたけど日本語消えちゃう (管理人日記)という記事より。
喜んだのもつかの間、日本語の文字を含むタグやコメントを書くと、その文字が消えてしまうようです。Plaggerではありがちな問題なような気がしますが、このPluginでも起きてしまいました。
確かに、ブラウザ上からだと日本語は見えるんですが、どうやらGoogleさんはUser-Agentを見て勝手にencodingをISO-8859-1に変えておられるようです。
# curl -L 'https://www.google.com/bookmarks/?output=rss' -u username:password
<?xml version="1.0" encoding="ISO-8859-1"?><rss vers
...
config.yamlの先頭に global:
  timezone: Asia/Tokyo
  user_agent:
    agent: Mozilla/5.0
を入れたら取得出来ました。
ブクマコメントで書こうかと思いましたが、記事が半月程前のものなので管理人さんも見てないかと思い、記事にしました。

それよりも...LivedoorClip.pmで Plagger [info] plugin Plagger::Plugin::Subscription::Config loaded.
Plagger [info] plugin Plagger::Plugin::UserAgent::AuthenRequest loaded.
Plagger [info] plugin Plagger::Plugin::Filter::GoogleBookmarksFeed loaded.
Plagger [info] plugin Plagger::Plugin::Publish::LivedoorClip loaded.
Plagger [info] plugin Plagger::Plugin::Bundle::Defaults loaded.
Plagger [info] plugin Plagger::Plugin::Aggregator::Simple loaded.
Plagger [info] plugin Plagger::Plugin::Summary::Auto loaded.
Plagger [info] plugin Plagger::Plugin::Summary::Simple loaded.
Plagger [info] plugin Plagger::Plugin::Namespace::HatenaFotolife loaded.
Plagger [info] plugin Plagger::Plugin::Namespace::MediaRSS loaded.
Plagger [info] plugin Plagger::Plugin::Namespace::ApplePhotocast loaded.
Plagger::Plugin::Aggregator::Simple [info] Fetch https://www.google.com/bookmarks/?output=rss
Plagger::Plugin::UserAgent::AuthenRequest [info] Adding credential to Google Search History at www.google.com:443
Plagger::Cache [debug] Cache HIT: Aggregator-Simple|https://www.google.com/bookmarks/?output=rss
Plagger::Plugin::Aggregator::Simple [debug] 200: https://www.google.com/bookmarks/?output=rss
Plagger::Plugin::Aggregator::Simple [info] Aggregate https://www.google.com/bookmarks/?output=rss success: 15 entries.
Died at C:/Perl/site/lib/WWW/Mechanize.pm line 1705.
なエラーが出る。なんぞ?
とりあえずcpan upgrade行ってきます。

追記1
GoogleBookmarksFeedで、tagsは1個でも配列で返ってきてそうだったので以下のように修正してます。もしかしたら間違ってるかも *** GoogleBookmarksFeed.pm.orig Tue Sep 04 11:39:49 2007
--- GoogleBookmarksFeed.pm  Tue Sep 04 11:40:15 2007
***************
*** 22,28 ****
              $args->{entry}->body($orig_body);
              $context->log(info => "Parsing Google Bookmarks title " . $args->{entry}->permalink);
          }
!         if (my @orig_tags = @{$args->{orig_entry}->{entry}->{$ns}->{bkmk_label}}) {
              $args->{entry}->tags(@orig_tags);
          }
      }
--- 22,28 ----
              $args->{entry}->body($orig_body);
              $context->log(info => "Parsing Google Bookmarks title " . $args->{entry}->permalink);
          }
!         if (my @orig_tags = $args->{orig_entry}->{entry}->{$ns}->{bkmk_label}) {
              $args->{entry}->tags(@orig_tags);
          }
      }
追記2
大嘘ついてました。tagsは1つの場合は文字、2つ以上の場合は配列で戻るみたいです。 *** GoogleBookmarksFeed.pm.orig Tue Sep 04 11:39:49 2007
--- GoogleBookmarksFeed.pm  Tue Sep 04 14:54:17 2007
***************
*** 22,29 ****
              $args->{entry}->body($orig_body);
              $context->log(info => "Parsing Google Bookmarks title " . $args->{entry}->permalink);
          }
!         if (my @orig_tags = @{$args->{orig_entry}->{entry}->{$ns}->{bkmk_label}}) {
!             $args->{entry}->tags(@orig_tags);
          }
      }
  }
--- 22,33 ----
              $args->{entry}->body($orig_body);
              $context->log(info => "Parsing Google Bookmarks title " . $args->{entry}->permalink);
          }
!         if (my $orig_tags = $args->{orig_entry}->{entry}->{$ns}->{bkmk_label}) {
!           if (ref($orig_tags) eq "ARRAY") {
!               $args->{entry}->tags($orig_tags);
!           } else {
!               $args->{entry}->tags([$orig_tags]);
!           }
          }
      }
  }
Posted at by




こんな夜中に何やってんだか...
お腹が空いてきたので、モスバーガーのホームページからメニューをスクレイピングしてみる。
別に買いに行く訳じゃないけど...

思った以上に苦戦。苦戦の理由は「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/
...
補足情報(場合によってはセットメニュー)も一緒に取得出来ます。

あー。はらへった。
Posted at by