#PHP成长

[PHP采集]基于querylist爬取P站的视频,利用aria2下载视频

距上一次爬取图片已经过去一个多月,期间由于不满足于图片的我开始打起了P站的注意,也成功的爬取了很多视频,苦于我留下了没有硬盘的泪,硬盘只有3T,现在还剩一百多G了,留着以后装其他重要的东西。研究这个代码和写这个代码可能花了接近大半个月吧,具体时间也记不清了,下载视频花了一段时间,慢速下10M每秒也下了挺久的,主要是要在服务器上中转一次。开始的时候疯狂的下,感觉就是几百年没看过电源一样,过了几天后发现,索然无味!,有小伙伴迫切的想学习下代码,so,我就分享出来。这个P站呢,估计大部分老司机都是懂得。在这里呢也发现个php的好东西 一个采集框架,这么好的一个东西怎么会没有早点发现他,此次的一个主角之一就是他了,采集框架。如果会点jquery的话用这个用起来应该是相当的顺手。只不过文档上面写的用法都比较基础,需要更深入的用法则需要自己深入了解下才行。具体怎么深入呢?来不及解释了,赶快上车。我是用的tp5.0的框架,composer引入进来的这个querylist。找到网址,最好带参数页码的这种比如:https://cn.xxxxxxx.com/video?c=111&page= 这种,这里只做技术交流

$rules = [
    'name'=>['.thumbnail-info-wrapper.clearfix>span>a','text'],
    'src'=>['.linkVideoThumb.js-linkVideoThumb.img','href'],
    'ima_src'=>['.js-pop.js-videoThumb.thumb.js-videoPreview.lazy','src'],
    'time'=>['.marker-overlays.js-noFade>var','text'],
    'hp'=>['.rating-container.neutral>.value','text'],
];
$sq = QueryList::getInstance();
//注册一个browser
        $sq->use(PhantomJs::class,'/项目目录/vendor/jaeger/querylist-phantomjs/phantomjs-2.1.1-linux-x86_64/bin/phantomjs','browser');
        for ($i=1;$i<=499;$i++){
            $page = $i;
            $url = 'https://cn.xxxxxx.com/video?c=111&page='.$page;
            $data = $sq->browser($url)
                ->rules($rules)
                ->queryData();
            $insert_data = [];
            $count = 0;
            foreach ($data as $k => $v){
                if ($k >= 4 && !empty($v['ima_src'])){
                    $v['time'] = $v['time'].':00';
                    $url = $host.$v['src'];
                    $v['src'] = $url;
                    $v['page'] = $page;
                    $v['type'] = 'rb';
                    $insert_data[] = $v;
                    $count++;
                }
            }
            $rst = Db::name('video_url')->insertAll($insert_data);
        }

我这里是存入的数据库,当然还可以做其他操作,比如这里开始循环直接下载视频。不过我是存入数据库选择性下载,上面的代码中PhantomJs这个是个插件,大概就是采集js渲染的页面,因为我的采集目标有些元素是js生成的,还有些什么伪元素的,这些我都不懂,不过只要能拿到数据就好了。那个$rules就是规则,类似于正则之类的,不过这个比正则速度快,他用的jq选择器。对于那个name我举个例子 这里'name'=>['.thumbnail-info-wrapper.clearfix>span>a','text'],这个就是选择同时拥有thumbnail-info-wrapper和clearfix这两种class属性的元素,这个元素从图中看出是个div,>就是找他的下级元素,找他的下级元素span标签,span标签的下级元素a标签,后面的‘text’就是找这个a标签的text文本内容也就是他的这部电影的名字,以此类推src是这个电影的链接,也就是播放地址,但并不是下载地址。我们既然能拿到这个播放地址了,这个播放地址是一直有效的,除非视频被下架了,所以这个地址可以存数据库,他和下载地址不一样。下载地址是有时间限制的,还有ip限制,所以下载地址需要及时的进行下载并不能长时间保存,具体时间我没测试过。进入这个地址后就可以找到下载地址了 在当时我并没有研究出如何登陆,在querylist的一个付费群里也没什么人鸟我,大概是大佬都很忙吧。关于这个js生成的下载地址我也是摸索了好久,各种查资料找到这个。我当时的一个解决方案是: 1、把所有视频的播放地址,封面地址,title和时长都储存到数据库。 2、写一个页面把数据根据封面渲染出来并做好分页。 3、点击封面的时候跳转后台抓取页面的一段js代码,php直接输出html和JavaScript,在js脚本里面生成一个带参数的按钮并赋值下载地址。 4、点击按钮,提交至后台推送给aria2下载。 这样能做到选择性的提交下载,并且不会有下载链接超时不能下载的情况。(因为下载有ip验证所以只能先下载到境外服务器,然后才能下载到本地) 不过后来还是找到了登陆下载的方法,可以挂代理登陆上去,获取cookie值,携带cookie请求链接,就会是登陆状态,cookie需要完全复制

        $list = ['视频列表集'];
        $rules = ['name'=>['.downloadBtn.greyButton','text'],'src'=>['.downloadBtn.greyButton','href']];
        $header = [
            'Accept'=>'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3',
            'Accept-Encoding'=>' deflate, br',
            'Accept-Language'=>'zh-CN,zh;q=0.9',
            'Cache-Control'=>'max-age=0',
            'Connection'=>'keep-alive',
            'Content-Type'=>'text/html; charset=UTF-8',
            'Cookie'=>"你成功登陆后的cookie",
            'Host'=>'cn.pornhubpremium.com',
            'Sec-Fetch-Mode'=>'navigate',
            'Sec-Fetch-Site'=>'none',
            'Sec-Fetch-User'=>'?1',
            'Upgrade-Insecure-Requests'=>'1',
            'User-Agent'=>'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.70 Safari/537.36',
        ];
        $sq = QueryList::getInstance();
        $sq->use(PhantomJs::class,'/项目地址/vendor/jaeger/querylist-phantomjs/phantomjs-2.1.1-linux-x86_64/bin/phantomjs','browser');
        foreach ($list as $k => $v){
            $aria2 = new \Aria2('http://127.0.0.1:6800/jsonrpc');
            $this->wait($aria2);
            $v['name'] = str_replace(' ','-',$v['name']).'.mp4';
            $v['name'] = str_replace('/','-',$v['name']).'.mp4';
            $data = $sq
                ->browser(function (RequestInterface $r)use ($header,$v){
                    $r->setHeaders($header);
                    $r->setMethod('GET');
                    $r->setUrl($v['src']);
                    $r->setTimeout(10000); // 10 seconds
                    return $r;
                })
                ->rules($rules)
                ->queryData();
            if (!empty($data)){
                 $data[0]['name'] = str_replace(' ','',$data[0]['name']);
                 $data[0]['name'] = str_replace('高清','',$data[0]['name']);
                 dump($data[0]);
                Db::name('video_url')->where('id','=',$v['id'])->update([$data[0]['name']=>1]);
                $rst = $aria2->addUri(
                    [$data[0]['src']],//下载地址
                    ['dir' => '/视频保存文件夹地址/', 'out'=>'['.$data[0]['name'].']'.$v['name'],]
                );
                echo '['.$data[0]['name'].']'.$v['name'];
                echo '提交aria2下载';
            }else{
                Db::name('video_url')->where('id','=',$v['id'])->update(['xiajia'=>1]);
                echo '已下架';
            }
            echo PHP_EOL;
        }

$r->setHeaders($header);这个方法querylist关于phantomjs插件的说明并未说明,phantomjs的官方文档,说实话,我确实没看懂。后来我怎么发现的这个方法我自己都不知道。当然这里我是默认下载的最高清的视频。这段代码中可能大家注意到了有一个aria2,这个就是我们今天的另一个主角,她是一个多线程下载器balabala一大堆,此处省略三千字,github有aria2-php代码,一搜就出来了,linux安装aria2也很好安装,yum一把梭,使用起来非常简单$rst = $aria2->addUri( [$data[0]['src']],//下载地址 ['dir' => '/视频保存文件夹地址/', 'out'=>'['.$data[0]['name'].']'.$v['name'],] );就这样就能够推送给aria2下载了。

← 返回首页