| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| use utf8; |
| use Encode; |
| use JE; |
| use Modern::Perl; |
| use File::Slurp; |
| use Mojo::UserAgent -signatures; |
| use Win32::Unicode::File; |
| use JSON qw/from_json to_json/; |
| STDOUT->autoflush(1); |
| |
| my $JE = new JE; |
| my $ua = Mojo::UserAgent->new()->with_roles('+Queued'); |
| my $loop = Mojo::IOLoop->singleton; |
| $loop = $loop->max_accepts(3); |
| $loop = $loop->max_connections(3); |
| $ua->max_active(5); |
| |
| init_ua(); |
| |
| my %headers; |
| init_headers(\%headers); |
| |
| my @list = qw/ |
| ph61668f9c9____视频ID1 |
| ph61668f9c9____视频ID2 |
| /; |
| |
| grep { getVideo($_) } @list; |
| |
| sub getVideo |
| { |
| my $viewkey = shift; |
| my $url = "https://cn.{P站}.com/view_video.php?viewkey=${viewkey}"; |
| |
| my ( $title, $major, $m3u8_content ) = get_m3u8( $url ); |
| |
| my $cache = gbk("E:/temp/ts"); |
| my $file = "E:/temp/${viewkey} ${title}.mp4"; |
| if ( file_type( 'e' => $file ) ) { |
| printf "%s: file already exists\n", $viewkey; |
| return; |
| } |
| mkdir $cache unless -e $cache; |
| |
| my $buff = ""; |
| for my $e ( grep { /^seg/ } split(/\r?\n/, $m3u8_content) ) |
| { |
| $e=~/(seg.*\.ts)/; |
| $buff .= "file ${1}\r\n"; |
| |
| my $tsfile = $cache ."/". $1; |
| |
| |
| |
| |
| $ua->get( $major . $e, closure->($tsfile) ); |
| |
| |
| |
| } |
| |
| $loop->start unless $loop->is_running; |
| write_file( $cache ."/". "content.txt", $buff); |
| |
| if ( -e "$cache/temp.mp4" ) |
| { |
| printf "temp.mp4 already exists ? \n"; |
| unlink "$cache/temp.mp4" if -e "$cache/temp.mp4"; |
| } |
| |
| system("ffmpeg -y -f concat -i \"$cache/content.txt\" -vcodec h264_nvenc -vb 2M \"$cache/temp.mp4\""); |
| moveW decode('gbk', "$cache/temp.mp4"), $file or warn $!; |
| |
| |
| |
| |
| |
| |
| |
| } |
| |
| sub get_m3u8 |
| { |
| my ($url) = @_; |
| |
| my $res = $ua->get( $url )->result; |
| |
| my $js = $res->dom->at(".video-wrapper #player script")->all_text; |
| my $id = $res->dom->at("#player")->attr("data-video-id"); |
| my $title = $res->dom->at("title")->text; |
| $title =~s/\s+- P...hub\.com//i; |
| $title =~s/[\\\/:*?"<>|]/ /g; |
| printf "%s %s\n", $id, gbk($title); |
| |
| |
| $JE->eval( $js ); |
| |
| my ($master_m3u8_url) = $JE->{"media_3"}->value; |
| $res = $ua->get( $master_m3u8_url )->result; |
| my ($major) = ($master_m3u8_url =~ /(.+\/)[^\/]+$/); |
| write_file("master.m3u8", $res->body); |
| |
| my ($index_m3u8) = ($res->body =~ /(index.+)\s/i); |
| printf "%s\n", $major . $index_m3u8; |
| $res = $ua->get( $major . $index_m3u8 )->result; |
| write_file("index.m3u8", $res->body); |
| |
| return ($title, $major, $res->body); |
| } |
| |
| sub closure ($file) |
| { |
| return |
| sub ($ua, $tx) { |
| printf "%s\n", $file; |
| if ( $tx->result->is_success ) { |
| write_file( $file, {binmode=>":raw"}, $tx->result->body ); |
| } else { |
| die "Failed to get segment $file\n"; |
| } |
| } |
| } |
| |
| sub init_headers |
| { |
| my $ref = shift; |
| %$ref = |
| ( |
| 'accept' => 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9', |
| 'accept-encoding' => 'gzip, deflate, br', |
| 'accept-language' => 'zh-CN,zh;q=0.9,zh-TW;q=0.8', |
| 'upgrade-insecure-requests' => '1', |
| 'user-agent' => 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/93.0.4577.82 Safari/537.36', |
| ); |
| } |
| |
| sub init_ua |
| { |
| $ua = $ua->max_redirects(5); |
| $ua = $ua->connect_timeout(10); |
| |
| |
| |
| |
| $ua->proxy->https("http://sri:secret\@127.0.0.1:10809")->http("http://sri:secret\@127.0.0.1:10809"); |
| |
| } |
| |
| |
| sub gbk { encode('gbk', $_[0]) } |
| sub utf8 { encode('utf8', $_[0]) } |
| sub u2gbk { encode('gbk', decode('utf8', $_[0])) } |
| sub uni { decode('utf8', $_[0]) }COPY |