Doge log

Abby CTO 雑賀 力王のオフィシャルサイトです

POEでRedTubeのビデオをダウンロードする

perlの勉強がてら。
Suger::Args使ってみた。
idが1〜10000のビデオを順に落とす。
(ほぼ全部落とす)

use strict;
use warnings;

use HTTP::Request::Common qw(GET);
use POE qw(Component::Client::HTTP Sugar::Args);

my @ids = 1..10000;
my $save_dir = "/tmp/";

my @map = qw(
        R 1 5 3 4 2 O 7 K 9 
        H B C D X F G A I J 
        8 L M Z 6 P Q 0 S T 
        U V W E Y N);

sub get_url {
    my $id = shift;
    my $dir = sprintf("%07d" , int($id / 1000));
    $id = sprintf("%07d", $id);
    
    my @id = split //, $id;
    my $my_int = 0;
    for my $i (0..6){
        $my_int += $id[$i] * ($i+1)
    }
    my @my_int = split // , $my_int;
    my $val = 0;
    for (@my_int){
        $val += $_; 
    }
    $my_int = $val;
    $val = sprintf("%02d", $val);
    my @val = split //, $val;
    my $mapping .= $map[ord($id[3]) - 48 + $my_int + 3]; 
    $mapping .= $val[1]; 
    $mapping .= $map[ord($id[0]) - 48 + $my_int + 2];
    $mapping .= $map[ord($id[2]) - 48 + $my_int + 1]; 
    $mapping .= $map[ord($id[5]) - 48 + $my_int + 6];
    $mapping .= $map[ord($id[1]) - 48 + $my_int + 5];
    $mapping .= $val[0];
    $mapping .= $map[ord($id[4]) - 48 + $my_int + 7];
    $mapping .= $map[ord($id[6]) - 48 + $my_int + 4];
    "http://dl.redtube.com/_videos_t4vn23s9jc5498tgj49icfj4678/$dir/$mapping.flv";
}

POE::Component::Client::HTTP->spawn( 
    Alias => 'ua', 
    Streaming => 4096,
);

sub got_response {
    my $id = shift;
    $id = sprintf("%07d", $id);
    return sub {
        my $poe = sweet_args;
        my $file = "$save_dir$id.flv";
        my $response_packet = $poe->args->[1];
        my ($response, $data) = @$response_packet;
        my $code = $response->code;
        if($code == 200){
            unless ($poe->heap->{$file}){
                print "write file = $file\n";
                open my $FILE, ">>", $file or die;
                $poe->heap->{$file} = $FILE;
            }
            my $FILE = $poe->heap->{$file};
            if (defined $data) {
                print $FILE $data;
            }else{
                close $FILE;
                $id = shift @ids;
                create_session($id) if $id;
            }
        }elsif ($code == 403){
            push @ids, $id;
        }else{
            print "id = $id return_code = $code\n";
            $id = shift @ids;
            create_session($id) if $id;
        }
    }
}

sub _start {
    my $id = shift;
    my $url = get_url($id);
    return sub{
        my $poe = sweet_args;
        print "id = $id request $url\n";
        $poe->kernel->post("ua" => "request", "got_response", GET $url);
    }
}
    
sub create_session {
    my $id = shift;
    my $f1 = _start($id);
    my $f2 = got_response($id);
    POE::Session->create(
        inline_states => { 
            _start => \&$f1,  
            got_response => \&$f2,
        }, 
    );
}

foreach (0..2){
    my $id = shift @ids;
    create_session($id);
}

$poe_kernel->run();

Streamingモードのサンプルってあんまり見かけないということはダウンローダーとして使用してないんだね、みんな。
ホントはRangeとか投げてレジュームできるようにしないといかんのだろうけど
基本3多重で動くはずなんだけど。4とかになったり。むむうーってところがあったりかなり適当。
あとファイルの書き出しもWheelとか使わないとダメなのかな。
やっぱPOEを使ってみたけどやっぱわからない所多いな。
そもそもperlの知識がまだまだ。
うくく。