Plagger::Plugin::Subscription::Toranoana

よつばの。を見てやった。悪気はなかった。つーか最初はCustomFeedとして作ってたんだけど、Subscriptionにするならhttp://www.toranoana.jp/shop/newka/shop.htmlからリンク抽出して個別のリスト取得すればいいじゃんと思った。まあいいや。EntryFullTextはめんどくさいのでまたこんど。
とらのあなRSSをPlaggerで、をインスパイアー - はこべにっき ♨に準じて画像を入れることに。この方法は最初からやるべきだよなーと思ってたんだけど、EntryFullText使うのがPlagger wayなのかなと思っていろいろ試してみたもののCookieの寿命がシビアなせいでMechanizeするFilterを書かないとEntryFullText相当のものはできそうにないっぽいね。
つーか画像を入れるととたんに使えるようになるな。テレホタイムあたりに巡回しよ。

Toranoana.pm

package Plagger::Plugin::Subscription::Toranoana;

use strict;
use warnings;

use base qw( Plagger::Plugin );

use Plagger::Util;
use Plagger::Feed;
use Plagger::Entry;

use URI;
use HTML::TreeBuilder::XPath;

sub register {
    my ($self, $context) = @_;
    $context->register_hook(
        $self,
        'subscription.load' => \&load,
    );
}

sub load {
    my($self, $context) = @_;

    my @tora_newka_shops = @{$self->conf->{shop}};
    
    my $day = $self->conf->{day} || _today(time);
    
    for my $shop (@tora_newka_shops) {
        my $feed = Plagger::Feed->new;
        $feed->aggregator( sub { $self->aggregate($context, $shop, $day); });
        $context->subscription->add($feed);
    }
}

sub aggregate {
    my($self, $context, $shop, $day) = @_;
    
    my $newka_uri = URI->new("http://www.toranoana.jp/shop/newka/${day}/${shop}_all.html");
    my $data = Plagger::Util::load_uri($newka_uri);
    
    my $tree = HTML::TreeBuilder::XPath->new;
    
    $tree->parse($data);
    my $path = '//body/div[3]/table';
    
    my $booknodes;
    eval {
        $booknodes = $tree->findnodes($path);
    } or die $@;
    
    my $feed = Plagger::Feed->new;
    $feed->title("Toranoana\@$shop $day");
    for my $book (@$booknodes) {
        $self->_add_entry($context, $feed, $book);
    }
    $context->update->add($feed);
}

sub _add_entry {
    my($self, $context, $feed, $book) = @_;
    
    my $html = $book->as_HTML('<>&');
    if (my @table = ($html =~ m|<td[^>]*>([^<]*)</td>|g)) {
        my $book_id = $table[0];
        
        if (
            ($html =~ /color\: \#FF99FF/)
            and ($self->conf->{yaoi_block})
            )
        {
            $context->log(info => "$book_id is yaoi");
            return;
        }
            
        my $book_dir = join '/', ($book_id =~ /^(\d{2})(\d{4})(\d{2})(\d{2})/);
        my $book_link = "http://www.toranoana.jp/mailorder/article/$book_dir/$book_id.html";
        
        my $book_body = 
            join '',
            map {
                "<img src=\"http://img.toranoana.jp/img/$book_dir/${book_id}-${_}.gif\" />"
            } (1..3);

        my $entry = Plagger::Entry->new;
        $entry->title($table[2]);
        $entry->link($book_link);
        $entry->body($book_body);
        $entry->author($table[1]);
        $entry->tags([$table[3]]);
        
        $feed->add_entry($entry);
    }
}

sub _today {
    my @t = localtime(shift);
    my $day = sprintf("%02d%02d", $t[4]+1, $t[3]);
    return $day;
}

1;

config.yaml

global:
  plugin_path: 
    - /Users/ec/lib/nolagger/nolagger
  timezone: Asia/Tokyo
  user_agent:
    cookies: /Users/ec/lib/cookies.txt

plugins:
  - module: Subscription::Toranoana
    config:
      shop:
        - aki1
        - bukuro
        - nagoya
      yaoi_block: 1

  - module: Publish::Feed
    config:
      dir: /Users/ec/Sites/tora_rss
      format: RSS
      filename: %t.rss