2008/01/31


Publish::Twitterコピって、Publish::Wassrをでっちあげた。
一応動いてる。TwitterからWassrへポストした結果
※テストでは1件だけポストした。

twitter2wassr.yaml
global:
  assets_path: /home/user/plagger/assets
  timezone: Asia/Tokyo
  log:
    level: info

plugins:
  - module: Subscription::Config
    config:
      feed:
        - http://twitter.com/statuses/user_timeline/[twitter user].rss

  - module: Filter::BreakEntriesToFeeds
    config:
      use_entry_title: 1

  - module: Publish::Wassr
    config:
      username: [user name]
      password: [pass word]

Plagger/Plugin/Publish/Wassr.pm
package Plagger::Plugin::Publish::Wassr;
use strict;
use base qw( Plagger::Plugin );

use Encode;
use Net::Wassr;
use Time::HiRes qw(sleep);

sub register {
    my($self, $context) = @_;
    $context->register_hook(
        $self,
        'publish.entry' => \&publish_entry,
        'plugin.init'   => \&initialize,
    );
}

sub initialize {
    my($self, $context) = @_;
    my %opt = (
        user => $self->conf->{username},
        passwd => $self->conf->{password},
    );
    for my $key (qw/ apihost apiurl apirealm/) {
        $opt{$key} = $self->conf->{$key} if $self->conf->{$key};
    }
    $self->{wassr} = Net::Wassr->new(%opt);
}

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

    my $body = $self->templatize('wassr.tt', $args);
    # TODO: FIX when Summary configurable.
    if ( length($body) > 159 ) {
        $body = substr($body, 0, 159);
    }
    $context->log(info => "Updating Wassr status to '$body'");
    $self->{wassr}->update( {status => encode_utf8($body)} ) or $context->error("Can't update wassr status");

    my $sleeping_time = $self->conf->{interval} || 15;
    $context->log(info => "sleep $sleeping_time.");
    sleep( $sleeping_time );
}

1;
__END__

=head1 NAME

Plagger::Plugin::Publish::Wassr - Update your status with feeds

=head1 SYNOPSIS

  - module: Publish::Wassr
    config:
      username: wassr-id
      password: wassr-password

=head1 DESCRIPTION

This plugin sends feed entries summary to your Wassr account status.

=head1 CONFIG

=over 4

=item username

Wassr username. Required.

=item password

Wassr password. Required.

=item interval

Optional.

=item apiurl

OPTIONAL. The URL of the API for wassr.jp. This defaults to "http://wassr.jp/user/xxx/statuses" if not set.

=item apihost

=item apirealm

Optional.
If you do point to a different URL, you will also need to set "apihost" and "apirealm" so that the internal LWP can authenticate.

    "apihost" defaults to "api.wassr.jp:80".
    "apirealm" defaults to "API Authentication".

=back

=head1 AUTHOR

Yasuhiro Matsumoto

=head1 SEE ALSO

L<Plagger>, L<Net::Wassr>

=cut
assets/plugins/Publish-Wassr/wassr.tt
[% IF entry.body %][% entry.body_text %][% ELSE %][% entry.title_text %][% END %] [% entry.permalink %]
deps/Publish-Wassr.yaml
name: Publish::Wassr
author: Yasuhiro Matsumoto
depends:
  Net::Wassr: 0

Net::Wassrは[Perl]Net::Wassr - Hatena::Diary::Neko::kak 500 Internal Server Errorを使用。
Posted at by




Exuberant ctags

ctags 5.7 improves Perl support

  • Added support for 'package' keyword
  • Added support for multi-line subroutine, package, and constant definitions
  • Added support for optional subroutine declarations
  • Added support for formats
  • Ignore comments mixed into definitions and declarations
  • Fixed detecting labels with whitespace after label name
  • Fixed misidentification of fully qualified function calls as labels
これ凄いす。もう朝からお腹いっぱいです。
さっそくWin32版試してみました。
改行されたメソッドにもジャンプ出来るし、余計なコメントにもヒットしないし、使いやすいです。
vimで開発する方のpluginフォルダには必ずと言って良いほど入っているtaglist.vimを使うとパッケージ名称も一覧されます。
パッケージやサブルーチンがキレイに一覧されます。
さらに今回「package」に対応したので、ちょっと時間は掛かりますが C:\Perl\site\lib>ctags -R -h ".pm"
こんな事して...
set tags=./tags,tags,../tags,c:/perl/site/lib/tags
こんな事しておくと...


ctags_beforejump
こんな状態でビジュアル選択しておいて、"C-]"を押す事で
ctags_afterjump
こんな感じにタグジャンプします。ウマーーー
複数含むモジュールだと、taglist.vimのTagListには複数のpackageが表示されます。

すばらしす...
Posted at by




Web::Scraper 0.15とcisco_scraper.pl
問題が一つ。添削してくださったパッチだと process '//li/node()[4]', 'title' => sub {$_->string_value;};
となっているのですが、4番目とは限らないんです。
たとえば、
http://www.cisco-records.co.jp/html/item/004/010/item393180.html
は何曲か試聴サンプルがないために、この処理だと取得できないです。
おろろ...
これはtext()でTextNodeを参照するしかないですね。
ただ、text()では改行等のゴミまで拾ってしまうので、以下のようにnormalize-space()で空文字ノードを省いています。
もしかすると、node()[2]も同じように修正した方がいいかもしれませんね。
#!/usr/bin/perl

use strict;
use warnings;

use Web::Scraper;
use URI;
use YAML;
use Data::Dumper;

my $uri = shift;

my %scraper;

$scraper{'link'} = scraper {
    process 'a', 'name' => 'TEXT';
    process 'a', 'uri'  => '@href';
    result qw/name uri/;
};

$scraper{'genre'} = scraper {
    process '//a[1]', 'top'   => $scraper{link};
    process '//a[2]', 'style' => $scraper{link};
    result qw/top style/;
};

$scraper{'track'} = scraper {
    process '//li/text()[normalize-space(.)!=""]', 'title' => sub {
        my $s = $_->as_XML;
        $s =~ s/\s+$//;
        return $s;
    };
    process 'li>a', 'uri' => '@href';
    result qw/title uri/;
};

$scraper{'item'} = scraper {
    process 'td.de_title',      'title'  => 'TEXT';
    process 'td.de_artist',     'artist' => 'TEXT';
    process 'td.nm_jacket>img', 'image'  => '@src';
    process 'td.de_price',              'price'   => 'TEXT';
    process 'td.de_label>a',            'label'   => $scraper{link};
    process 'td.de_genre',              'genre'   => $scraper{genre};
    process 'td[headers="de_format"]',  'format'  => 'TEXT';
    process 'td[headers="de_release"]', 'release' => 'TEXT';
    process 'td[headers="de_country"]', 'country' => 'TEXT';
    process 'td[headers="de_sheet"]',   'sheet'   => 'TEXT';
    process 'td[headers="de_arrival"]', 'arrival' => 'TEXT';
    process 'td[headers="de_nomber"]',  'number'  => 'TEXT';
    process '//p[@class="de_star"]/node()[2]', 'star' => 'TEXT';
    process 'ul[id="de_sound"]>li', 'tracks[]' => $scraper{track};
    result
        qw/title artist image price label genre format release release country sheet arrival number star tracks/;
};

my $item = $scraper{'item'}->scrape( URI->new($uri) );
warn Dump $item;
あと、ブックマークコメント
コールバック渡しだと相対URLの展開がされないのは僕だけ?
との事ですが...少し調べてみた所Web::Scraper側でパッチが必要かもしれません。
以下svn/trunk(rev2351)からの差分です。
Index: lib/Web/Scraper.pm
===================================================================
--- lib/Web/Scraper.pm  (revision 2351)
+++ lib/Web/Scraper.pm  (working copy)
@@ -152,12 +152,12 @@
         local $_ = $node;
         return $val->($node);
     } elsif (blessed($val) && $val->isa('Web::Scraper')) {
-        return $val->scrape($node);
+        return $val->scrape($node, $uri);
     } elsif ($val =~ s!^@!!) {
         my $value =  $node->attr($val);
         if ($uri && is_link_element($node, $val)) {
             require URI;
-            $value = URI->new_abs($value, $uri);
+            $value = URI->new_abs($value, $uri)->as_string;
         }
         return $value;
     } elsif (lc($val) eq 'content' || lc($val) eq 'text') {
Posted at by