2009年07月25日

get_video_infoによるflvurl取得

youtubeの動画データは
「watch」が一般的なアクセスで「/v/」が埋め込み用swfで
「get_video」がflv取得のブラウザ用のインターフェースであるが
他に「get_video_info」というAPIがある事が分かった。
但しこのAPIは定期的に仕様が変わっているらしい。(今年の4月4日あたり)
Flashからのアクセスを考えるとrefererは読まないと思うが
useagentやIPで拒絶されることがあるらしいがローカル使用ならば問題なさそうだ。
書式は


http://www.youtube.com/get_video_info?video_id=ビデオID

返り値はURI風味なので&と=でsplitしてやればnameとpropertyの配列になる。

ここでひとつ問題がある。「出発点」だ。
一貫したアプリとして扱うのであれば抽出されたURLからIDを求めるのはシンプルな方法で良い。
しかしブラウザからurlをコピペしたりした場合余計なパラメータがついていたりすることもある。
それが意味をなすこともあるのだろうがとりあえず「無難な」フィルターをかけてやることにした。

一般的な出発点、それは


http://www.youtube.com/watch?v=ビデオID&オプション

と表現される視聴ページのURLだ。

ブラウザでurlバーをコピペしたところを出発点に考え
perl用としてxclipを使って取得する。
ここはshiftなどにおきかえてもいい。


my $uri1= `xclip -selection clipboard -o`;

my @urls =split(/&/,$uri1);
$urls[0]=~ /v=(.+?)$/;
my $ID=$1;
my $url = 'http://www.youtube.com/get_video_info?video_id='.$ID;


次にCurlの準備


my $rbody;
open (my $FH, "+>", \$rbody);

my $curl = WWW::Curl::Easy->new();
$curl->setopt( CURLOPT_WRITEDATA, $FH);
$curl->setopt(CURLOPT_FOLLOWLOCATION, 1);
$curl->setopt( CURLOPT_URL, $url );
$curl->setopt(CURLOPT_TIMEOUT, 30);


データを取得


my $resp = $curl->perform;
$curl->close;
close($FH);


この後は正規表現を使っても良いけれど一様に入っているので
重複はないのでhashで良いと思う。
いろいろな動画をチェックしたら順番はばらばらなので
もしも正規表現を使って切り出すのであれば
取得した文字列の前後に「&」をつけて


$rbody=~/&パラメータ名=(.+?)&/;

とすることができる。
hashにするならば


my @prms = split(/&/,$rbody);
my ($name, $val);
my %param = {};
foreach ( @prms ) {
($name, $val) = split(/=/, $_);
$param{ $name } = $val;
}
my $status=$param{'status'};
if ($status eq 'fail'){
print 'アクセスできません';
exit(1);


とする。
statusがfailであれば動画は削除されているなりしているということになるので
ここでおしまい。

ここで


$param{ $name } = uri_unescape($val);

と復元をかましてしまってもさほど構わないが

楽しようとして


$rbody =uri_unescape($rbody)

と一回で全部処理すると
してしまうと「&」が複数現れるのでsplitが効かなくなる。
分解した後、ないしは値を取り出すときに変更するのが良い。
URIでこの辺は必須なのになんで実装されていないか謎。

で、flvのurlは22でとらず35または18にするケースでは


my $t = $param{'token'};
print("$t\n");
my $fmt = uri_unescape($param{'fmt_map'});
print("$fmt\n");
$fmt =~/(.+?)\//;
my $fm=$1;
if ($fm ==22){$fm=35;}
if ($fm !=35){$fm=18;}
my $mp4url="http://www.youtube.com/get_video?video_id=$ID&t=$t&fmt=$fm";



ままでやる場合は



if (($fm !=22) && ($fm !=35)){$fm =18;}


その他取り出せるパラメータとして

改めてID,投稿者、再生時間がunescape無しで
タイトル、キーワード、サムネールのURLがunescapeをすることで取得できる。


my $vid = $param{'video_id'};
my $author = $param{'author'};
my $v_len = $param{'length_seconds'};

my $title = uri_unescape($param{'title'});
my $keywds = uri_unescape($param{'keywords'});
my $thumb = uri_unescape($param{'thumbnail_url'});



案外と情報量が少ない。1kbyte程度なんだからしょうがないか。
それでもタイトル、投稿user、キーワードが取得できるから必要充分ではある。
情報が欲しければやはりwatchのhtml 100kbyte強を
読み込んでパースする方が良いのかもしれない。


posted by Xo_ox at 19:00| Comment(0) | perl | このブログの読者になる | 更新情報をチェックする
この記事へのコメント
コメントを書く
お名前:

メールアドレス:

ホームページアドレス:

コメント:

認証コード: [必須入力]


※画像の中の文字を半角で入力してください。
×

この広告は180日以上新しい記事の投稿がないブログに表示されております。