にたまごほうれん草アーカイブ

はてなダイアリーで書いてた「にたまごほうれん草」という日記のアーカイブです。現在は「にたまごほうれん草ブログ」を運営中です。

Filter::FetchNicoVideoを、ローカルにFLVがあったらアクセスしないようにした

後者の記事にあるとおり、確かに、

 Plaggerニコニコ動画をダウンロード&変換できるようになったのはいいんですが、すでに変換済みの動画がローカルに大量にあったりすると、
短時間に多数のアクセスが発生

  • > ニコニコ運営側に怒られる
  • > 動画が(一時的に)ダウンロードできなくなる

という悲しい事態が発生してしまいます。

は発生するのですが、だったらローカルに動画があるときはニコニコ動画にアクセスしなければいいのでは?と思ったのでcodereposSVNの最新をベースに、手元で修正してみました。
ローカルに動画があるときは、

  • $enclosure->urlはセットしない(どうせ使わないから)
  • $enclosure->lengthには、statでファイルサイズを取得して突っ込む

としており、乱暴な気がしないでもないですが、この使い方では今のところ困っていません。
diffは以下の通り。

Index: FetchNicoVideo.pm
===================================================================
--- FetchNicoVideo.pm	(リビジョン 2815)
+++ FetchNicoVideo.pm	(作業コピー)
@@ -51,6 +51,28 @@
     #get video_id
     my ($video_id) = $entry->link =~ m!www.nicovideo.jp/watch/(.*)!;
 
+    #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" );
+    
+    # declare new enclosure
+    my $enclosure = Plagger::Enclosure->new;
+    $enclosure->media_type("video/x-flv");
+    $enclosure->filename($filename);
+    $enclosure->local_path($path);    # set to be used in later plugins
+
+    if ( -e $path ) {
+        $context->log( info => "$filename is already exists" );
+	my $filesize = (stat $path)[7];
+	$enclosure->length($filesize); # use file size instead of Content-Length
+	$entry->add_enclosure($enclosure);
+	return;
+    }
+
     #get flv url
     my $res = $ua->get("http://www.nicovideo.jp/api/getflv?v=$video_id");
     my $q   = CGI->new( $res->content );
@@ -62,28 +84,16 @@
     }
     $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
-     unless ( -e $path ) {
-     my $req = HTTP::Request->new(GET => $enclosure->url);
-         $context->log(info => "Fetching $video_id FLV File from " . $enclosure->url . "..." );
-         my $res = $ua->request($req, $path);
-         $context->log(warn => "Fetch FLV Error: $video_id" ) if $res->is_error;
-    }
+    my $req = HTTP::Request->new(GET => $enclosure->url);
+    $context->log(info => "Fetching $video_id FLV File from " . $enclosure->url . "..." );
+    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} ) {
@@ -101,8 +111,6 @@
 	}
     }
 
-    $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') );
     }

追記

>kamawadaさん(ゆーすけべーさん?)

Plagger的にはDedupedをうまく使うってのが解決方法かな。俺はそうしてる。Plugin側で対応してもいいけど。

なるほど、Dedubpedという存在をすっかり忘れてました。ただ、私の使い方は「ジャンルごとにマイリストを作ってcronで毎日深夜に一気に更新を取得する」で、この場合1日更新分の取得を忘れると、DedupedでPodcastRSSから除外されてしまい、iPodに入れられなくなるのではないかと思うのです。
また、元のプラグインで、FLVがローカルに存在する場合には新たにダウンロードしないようにされていますが、それでも動画ページへのアクセスは一度行っています。上記はこれを行わないように修正しています。
コメントをDLする場合のことは全く考えてないんですけどね…。