カラクリサイクル

『輝かしい青春』なんて失かった人の雑記

Plagger::Plugin::Subscription::XPath::Config

概要: もうちょっといじりやすいかもしれないSubscription::XPath


Plaggerでフレーム使ってるページからフレームに表示されてるページを引っこ抜きたいと思って、 Subscription::XPathを使おうかと思ったんだけど、Subscription::XPathはページのURLを一個しか指定できないのと、 XPathで取得した要素から取り出す属性が固定されてるので、 Subscription::ConfigとSubscription::XPathを参考にプラグインを作ってみた。

package Plagger::Plugin::Subscription::XPath::Config;
use strict;
use warnings;
use base qw( Plagger::Plugin );
use Plagger::Util;
use HTML::TreeBuilder::XPath;
use Encode ();
use URI;
sub register {
    my ( $self, $c ) = @_;
    $c->register_hook(
        $self,
        'subscription.load' => $self->can('load'),
    )
}
sub load {
    my ( $self, $c ) = @_;
    my $feeds = $self->conf->{'feed'} or return;
       $feeds = [ $feeds ] if ( ! ref $feeds || ref $feeds eq 'HASH' );
    my $default = $self->conf->{'default_node'} || {
        xpath       => '//a',
        url_attr    => 'href',
        title_attr  => 'title',
    };
    for my $config ( @{ $feeds } ) {
        unless ( ref $config ) {
            $config = {
                url     => $config,
                node    => $default,
            };
        }
        Encode::_utf8_off( $config->{'url'} );
        $config->{'node'}->{'xpath'}        ||= $default->{'xpath'};
        $config->{'node'}->{'url_attr'}     ||= $default->{'url_attr'};
        $config->{'node'}->{'title_attr'}   ||= $default->{'title_attr'};
        if ( my $tags = $config->{'tag'} ) {
            unless ( ref $tags ) {
                $tags = [ Plagger::Tags->parse( $tags ) ];
            }
            $config->{'tag'} = $tags;
        }
        $self->find_feed( $c, $config );
    }
}
sub find_feed {
    my ( $self, $c, $config ) = @_;
    my $uri = URI->new( $config->{'url'} )
        or $c->log( error => 'Fetch url is missing.' ) and return;
    my $xhtml   = Plagger::Util::load_uri( $uri, $self );
    my $tree    = HTML::TreeBuilder::XPath->new;
    $tree->parse( $xhtml );
    $tree->eof;
    my $node = $config->{'node'};
    for my $child ( $tree->findnodes( $node->{'xpath'} ) ) {
        my $path    = $child->attr( $node->{'url_attr'} ) or next;
        my $title   = $child->attr( $node->{'title_attr'} ) || $child->as_text;
        my $feed = Plagger::Feed->new;
        $feed->url( URI->new_abs( $path, $uri ) );
        $feed->title( $title )              if ( $title );
        $feed->meta( $config->{'meta'} )    if ( $config->{'meta'} );
        $feed->tags( $config->{'tag'} )     if ( $config->{'tag'} );
        $c->subscription->add( $feed );
    }
}
1;
__END__

ライセンスはPerlと同等で。設定はこんな感じ。globalは省略。

plugins:
  - module: Subscription::XPath::Config
    config:
      default_node:
        xpath: //a
        url_attr: href
        title_attr: title
      feed:
        - url: http://example.com/foo/bar.html
        - url: http://example.com/foo/bar/baz.html
          node:
            xpath: //frame
            url_attr: src

設定の細かいところはソースみて判断してください。説明がめどい。 たぶん変なところは無いと思いますが、おかしいところがあったら教えてください。

名前が微妙な気がするのと、車輪の再開発になってないかなーとか思う。 が、フレームからフレーム内のページをFeedとして引っこ抜くプラグインがなかったので作ってみた次第。

とりあえずフレームからフレームページ引っこ抜けるようにはなった。