せかいろぐ

ほぼ自分用備忘録

PerlでニコニコAPIを叩いてマイリストの動画をすべて保存

PerlのLWP::UserAgentでニコニコAPIを叩いてみる。

2014-08-26 : 修正

ログインする

https://secure.nicovideo.jp/secure/login?site=niconicoにメールアドレス・パスワードをPOSTします。以下必要なPOSTパラメータ。

mail_tel ログインに用いるメールアドレス
password ログインに用いるパスワード

マイリストから動画IDを取得

http://www.nicovideo.jp/mylist/<マイリストID>?rss=2.0にGETします。XML(RSS)が返ってくるので、パースして動画IDを取得します。XML::Simpleなんかを使うとカンタン。

動画情報を取得

http://ext.nicovideo.jp/api/getthumbinfo/<動画ID>にGETして動画情報(タイトルとかサイズとか)をXMLで取得します。

動画データのURLを取得

http://flapi.nicovideo.jp/api/getflv/<動画ID>にGETして動画がおいてある場所を取得します。url=http://...がURLです。

再生ページにアクセスしてCookieを受け取る

ここで結構ハマったんですが、再生ページにアクセスした時に貰えるCookieを持ってないと動画を取りに行こうとしても403で弾かれるみたいです。http://www.nicovideo.jp/watch/<動画ID>にHEADすればok。

落とす

あとは先ほど取得したURLにGETして保存します。

コード

use utf8;
use strict;
use Encode;
use XML::Simple;
use URI::Escape;
use LWP::UserAgent;

# エンコーディング
my $encode = "CP932";
# マイリストID
my $mylist_id = 0;
# ログイン情報
my $login_info = {
	mail_tel => 'your@mail.addr',
	password => 'your_passwd'
};

my $ua = LWP::UserAgent->new(cookie_jar => {});

# ログイン
$ua->post("https://secure.nicovideo.jp/secure/login?site=niconico", $login_info);
print("Logged in\n");

# マイリスト情報取得
my $mylist = XMLin($ua->get("http://www.nicovideo.jp/mylist/${mylist_id}?rss=2.0")->content);

foreach(@{$mylist->{channel}->{item}}){
	# 動画ID取得
	$_->{link} =~ /([^\/]+)$/;
	my $id = $1;

	# 動画情報取得
	my $info = XMLin($ua->get("http://ext.nicovideo.jp/api/getthumbinfo/${id}")->content)->{thumb};

	# 動画ファイルのURL取得
	$ua->get("http://flapi.nicovideo.jp/api/getflv/${id}" . ($info->{movie_type} eq "swf" ? "?as3=1" : ""))->content =~ /url=([^&]+)/;
	my $url = uri_unescape($1);

	# 再生ページにアクセスしCookieを受け取る
	$ua->head("http://www.nicovideo.jp/watch/${id}");
	
	# ファイル名を決める
	my $fname = encode($encode, "${id} - $info->{title}.$info->{movie_type}");
	$fname =~ s/[\\\/:*?"<>|]/_/g;
	
	if(-s $fname){
		print("Skipped(File exists): ${fname})\n");	
	# エコノミーモード時はDLしない
	#}elsif($url =~ /low$/){
	#	print("Skipped(Economy mode): ${fname}\n");
	}else{
		$ua->get($url, ":content_file" => $fname);
		print("Saved: ${fname}\n");
	}
	
	# 連続アクセスすると弾かれるので待つ
	sleep(3);
}