概要: もうちょっといじりやすいかもしれない 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 として引っこ抜くプラグインがなかったので作ってみた次第。
とりあえずフレームからフレームページ引っこ抜けるようにはなった。
#FIXME