« Danさんに勝手に添削されて学んだこと | メイン | Catalystのモデルを外部スクリプトから操作する(Loaderが0.03007の場合) »

Plagger::Plugin::Filter::FetchNicoVideo / ver0.01

非公式なニコニコ動画のAPIの制限を加味して、linkがニコニコ動画のビデオページ(http://www.nicovideo.jp/watch/sm000000形式)のエントリーだった場合に、動画のFLVとコメントのXMLをダウンロードできるPlaggerのPluginを作った。 制限のあるニコニコ動画向けに、Filter::FindEnclosuresとFilter::FechEnclosureをあわせたようなもの。 外部クッキーを使ってユーザー名とパスワードを書かなくてよくすることもできるが、とりあえず、必須にした。あとコメント数をオプションで設定するようにしたい。今は500件。 詳しい使い方は→ゆーすけべー日記: Plaggerでニコニコ動画のFLVとコメントを一括ダウンロード!


package Plagger::Plugin::Filter::FetchNicoVideo;
use strict;
use base qw( Plagger::Plugin );

our $VERSION = 0.01;

use URI::Escape;
use File::Spec;
use HTTP::Request;
use Plagger::Enclosure;
use Plagger::UserAgent;

sub register {
    my($self, $context) = @_;
    $context->register_hook(
        $self,
        'update.entry.fixup' => \&filter,
    );
        my $ua  = Plagger::UserAgent->new;
        $ua->cookie_jar( $self->cookie_jar );
        $self->{ua} = $ua;
        $self->login();
}

sub init{
    my $self = shift;
    $self->SUPER::init(@_);

    defined $self->conf->{mail} or Plagger->context->error("conifg 'mail' is not set.");
    defined $self->conf->{password} or Plagger->context->error("config 'password' is not set.");
    defined $self->conf->{dir} or Plagger->context->error("config 'dir' is not set.");

    if ($self->conf->{dir} =~ /^[a-zA-Z]/ && $self->conf->{dir} !~ /:/) {
        $self->conf->{dir} = File::Spec->catfile( Cwd::cwd, $self->conf->{dir} );
    }
    
    unless (-e $self->conf->{dir} && -d _) {
        Plagger->context->log(warn => $self->conf->{dir} . " does not exist. Creating");
        mkpath $self->conf->{dir};
    }
}


sub filter {
    my($self, $context, $args) = @_;
        my $ua = $self->{ua};
        my $entry = $args->{entry};

        #get video_id
        my $video_id;
        $_ = $entry->link;
        return unless (m!www.nicovideo.jp/watch/(.*)!);
        $video_id = $1;

        #get flv url
        my %prop = $self->find_property($video_id);
        my $flv_url = $prop{url};
        unless($flv_url){
                $context->log(warn => "Not Found FLV URL $prop{error}: $video_id");
                return;
        }
        $context->log(info => "Found FLV URL $flv_url");
        my $enclosure = Plagger::Enclosure->new;
        $enclosure->url( URI->new($flv_url) );
        $enclosure->media_type( "video/x-flv" );

        #set local path
        my $filename = $self->conf->{id_as_filename} ? $video_id : $entry->title;
        utf8::encode($filename);
        if($self->conf->{filename_encode}){
                Encode::from_to($filename, "utf-8", $self->conf->{filename_encode});
        }
        my $path = File::Spec->catfile($self->conf->{dir}, $filename . ".flv");

        #access video page
        $ua->get( "http://www.nicovideo.jp/watch/$video_id" );

        #download flv file
        my $req = HTTP::Request->new(GET => $enclosure->url);
        $context->log(info => "Fetching $video_id FLV File ... " );
        my $res = $ua->request($req, $path);
        $context->log(warn => "Fetch FLV Error: $video_id" ) if $res->is_error;

        #download xml file
        if($self->conf->{download_comment}){
                $path = File::Spec->catfile($self->conf->{dir}, $filename . ".xml");
                my $post_data = qq!<thread res_from="-500" version="20061206" thread="$prop{thread_id}" />"!;
                my $header = HTTP::Headers->new;
                $header->header('Content-Type' => 'text/xml');
                my $req = HTTP::Request->new('POST', $prop{ms}, $header, $post_data );
                $context->log(info => "Fetching $video_id XML File ... " );
                $res = $ua->request($req, $path);
                $context->log(warn => "Fetch XML Error: $video_id" ) if $res->is_error;
        }
        
        $enclosure->filename($filename);
        $enclosure->local_path($path); # set to be used in later plugins
        if ($res->header('Content-Length')) {
                $enclosure->length( $res->header('Content-Length') );
        }
        $entry->add_enclosure($enclosure);

}

sub login {
        my $self = shift;
        my $res = $self->{ua}->post( "http://www.nicovideo.jp/login",
                             [
                                mail => $self->conf->{mail},
                                password => $self->conf->{password},
                        ]);
        return $res->content;
}

sub find_property {
        my($self, $video_id) = @_;
        my $res = $self->{ua}->get( "http://www.nicovideo.jp/api/getflv?v=$video_id");
        return if $res->is_error;
        my $content = URI::Escape::uri_unescape($res->content);
        my %data;
        my @temp = split("&",$content);
        foreach my $prop (@temp){
                if($prop =~ /(.*?)=(.*)/){
                        $data{$1} = $2;
                }
        }
        return %data;
}


1;

__END__

=head1 NAME

Plagger::Plugin::Filter::FetchNicoVideo - Fetch flv file from NicoVideo link

=head1 SYNOPSIS

  - module: Filter::FetchNicoVideo
    config:
      mail: your@mailadddres
      password: yourpassword
      dir: /path/to/files
      download_xml: 1 #optional default is 0
      filename_encode: euc-jp #optional default is utf-8

=head1 DESCRIPTION

This plugin downloads flv file for each entry which has NicoVideo link.

=head1 CONFIG

=over 4

=item mail password

Your NicoVideo login mail address and password.

=item dir

Directory to store downloaded enclosures. Required.

=item download_xml

IF set, download comment xml file. Optional. Default is off.

=item filename_encode

File name encode. Example: euc-jp / shift-jis. Optional. Default is utf-8.

=item id_as_filename

IF set, set video id as flv file. Default file name is entry title. Optional.

=back

=head1 AUTHOR

Yusuke Wada

=head1 SEE ALSO

L<Plagger>, L<http://www.nicovideo.jp/>

=cut


トラックバック

このエントリーのトラックバックURL:
http://yusukebe.com/mt/mt-tb.cgi/2140

この一覧は、次のエントリーを参照しています: Plagger::Plugin::Filter::FetchNicoVideo / ver0.01:

» Plaggerでニコニコ動画のFLVとコメントを一括ダウンロード! 送信元 ゆーすけべー日記
暇さえあればニコニコ動画。 今日はそんなニコニコ動画をPlaggerを使ってもっと楽しむ方法( = ニコプラ)を教えちゃいます。 Plagg... [詳しくはこちら]

» ニコニコ動画からPlaggerでPodcastを作りiTunesで見たいゼ 送信元 WeBlog!
どうも。iPod Touchをアップルストアで初日に予約しながらAmazonポ... [詳しくはこちら]

コメント (1)

先日のログイン方法変更によりログイン先が変わったようです。
とりあえず下記変更でログインはいけました。(ニコRSSの挙動も多少変わってる気もしますが未検証です)
変更前
my $res = $self->{ua}->post( "http://www.nicovideo.jp/login",
変更後
my $res = $self->{ua}->post( "https://secure.nicovideo.jp/secure/login?site=niconico",

ご報告までに。

コメントを投稿

(いままで、ここでコメントしたことがないときは、コメントを表示する前にこのブログのオーナーの承認が必要になることがあります。承認されるまではコメントは表示されません。そのときはしばらく待ってください。)


ブログSEO対策:track word seo