- 2009年4月 8日 22:55
- flash
前回から1ヶ月もたたないうちに Youtube の仕様が変更された模様(2009年4月4日〜)。地味に悩んで解決方法も見つけました。
今回の仕様変更について(推測含む)
まず目に見える現象としては
- get_video の api は変わっていない(video_id と t を渡せばOK)
- トークン(token または t)が一定ではなくなった(アクセスすると変わる)
- 通常の Embed 用 swf やローカルからアクセスすれば、時間が経過してもどのトークンも有効
- サーバを介してトークンを取得する(前回の方法やスクレイピング等)方法では get_video のレスポンスが 403 になる
- こんな感じでローカルからアクセスすればロードできる
これらの状況から推測すると、「アクセス単位でトークンを発行して、トークン取得時のリファラが同じでないと、get_video に正しいトークンを渡しても 403 が返される」っていう仕様になったのかなーと。裏側の知識があまりないのでここらへんが限界(昨日の夜はココで思考が停止してた)。
get_video のレスポンスヘッダを参照する
推測が正しいなら、プロキシを使ってトークンを取得して swf側から flv にアクセスすると異なるリファラになってしまう。なら、トークン取得後、ついでに get_video から 303 See Other で返されるレスポンスヘッダ中のLocation から google video の URL を見ればいい。
#!/usr/bin/perl
use strict;
use warnings;
use LWP;
use URI;
use CGI;
my $query = CGI->new;
my $id = $query->param('id');
my $ua = LWP::UserAgent->new();
my $req = HTTP::Request->new(GET=> "http://www.youtube.com/get_video_info?video_id=$id" );
my $res = $ua->request( $req );
my @pairs = split(/&/,$res->content);
my ($name, $val);
my %querys = {};
for ( @pairs ) {
($name, $val) = split(/=/, $_);
$querys{ $name } = $val;
}
my $t = $querys{'token'};
$req = HTTP::Request->new(POST => "http://www.youtube.com/get_video?video_id=$id&t=$t" );
$res = $ua->request( $req );
$req = HTTP::Request->new(GET => "http://www.youtube.com/get_video?video_id=$id&t=$t" );
$res = $ua->simple_request( $req );
my $uri = URI->new($res->header('Location'));
print "Content-type: text/plain\n\n";
print $uri;
これで本当にいけた!
サンプル
2009-05-30T02:43:20+09:00 ステータスコードが 411 になっていたので修正。
- Newer: 実はパンダやってました
- Older: MEMO:Youtube の動画URLを取得する