获取网页中的视频下载地址(用headless browser)

介绍

前面通过两篇文章讲了怎么去抓取HTTP的请求包,包括用代理服务器和抓包的方法。正因为现在的视频网站的视频地址都不是直接在html页面上获取的,视频的获取是通过浏览器动态解释js脚本,再向视频服务器发去视频请求。所以我们通过获取浏览器产生的HTTP请求来获得视频的下载地址。

思路

直接用firefox

我们想到了可以用动态渲染js脚本的程序,最常见的是浏览器。我们通过命令运行

firefox http://the.video.url

就可以用firefox打开网址了。可是我们没办法在没有显示的情况下这样使用,但是我们后面有方法解决这个问题。

python+selenium+Phantomjs

因为我们需要在没有界面显示的情况下渲染JS脚本,我们还想到了python+selenium+Phantomjs来动态渲染页面。Phantomjs是一个headless browser(Headless Browser就是没有界面的浏览器)。
可是Phantomjs 1.5版本以后,就不再支持flash插件了。换句话说,虽然Phantomjs能动态加载JS脚本,但是没办法渲染视频。所以不会发出获取视频的HTTP请求。
我通过截图获取渲染后的页面,如下图:
figure1
视频播放窗口那里是黑色的,抓包程序抓不到带有flv字符串的HTTP请求。
我还尝试了1.4.1版本的Phantomjs,网上说可以通过这个命令加载Flash插件
./bin/phantomjs --load-plugins=yes examples/snap.js
通过渲染JS脚本,截图得到下图:
figure2
虽然得到的截图跟上图不一样,视频那里多了一个加载的状态,可是我还是抓取不到视频HTTP请求。最后,我在python中调用webdriver.Phantomjs()的时候报错.

WebDriverException: Message: Can not connect to the Service phantomjs

最后不得不放弃使用Phantomjs

slimerjs

我在网上搜索headless browser时,另外还有搜到slimerjs。

PhantomJS与SlimerJS异同:来自这篇文章

  1. PhantomJS 基于 Webkit 内核,不支持 Flash 的播放
  2. SlimerJS 基于火狐的 Gecko 内核,支持 Flash播放,并且执行过程会有页面展示

正好我们需要支持Flash播放。可是问题又来了!SlimerJS不是一个纯正的Headless browser,它需要DISPLAY!!。那么我们有什么办法可以解决这个问题呢?有!

xvfb

xvfb 是通过提供一个类似 X server 守护进程 和 设置程序运行的环境变量 DISPLAY 来提供程序运行的环境
通过这个,也可以解决前面所说到的第一个Firefox遇到的问题了。感觉好像兜了个圈= =!

程序实现

最后我们决定用slimerjs来获取页面。因为没办法通过python的selenium的方法调用slimerjs,那么我们只能通过python调用命令行程序的方法来动态渲染页面了。slimerjs脚本如下,我们调用这个脚本的时候,传入一个网页地址参数。slimerjs就负责打开这个页面,渲染页面的内容。
这个脚本的文件名是getPage.js

 var page = require('webpage').create();
 var videoUrl = phantom.args[0];
 var page.open(videoUrl, function (){      
      window.setTimeout(function(){
            phantom.exit();
      },10);
});

我们python调用os.system("xvfb-run slimerjs getPage.js " + videoURL)来渲染视频URL的视频。

我们最终的python程序是slimerjs_crawl_video.py

import os
import time
open163url = 'http://open.163.com/movie/2016/1/T/D/MBCRLBLRN_MBCRM7OTD.html'
startTime = time.time()
os.system("xvfb-run slimerjs getPage.js " + open163url)
print "use time: " + str(time.time() - startTime)
➜ capture_traffic sudo python pypcap_test.py
[sudo] password for honkee:
starting capture
mov.bn.netease.com/open-movie/nos/flv/2016/01/20/SBCRM4HFN_hd.flv
mov.bn.netease.com/open-movie/nos/flv/2016/01/20/SBCRM4HFN_hd.flv?start=107570066

获取到视频地址!!

未解决问题

调用python slimerjs_crawl_video.py

➜  capture_traffic python slimerjs_craw_video.py
Vector smash protection is enabled.
use time: 94.3547639847

这个时间我还不知道怎么控制,我试过修改getPage.jswindow.setTimeout函数的时间,可是这个用时还是90多秒,我猜测是python的os.system()的限制是阻塞一定时间(90多秒)就返回吧。接下来我再查一查相关的东西。

更新:
今天为了解决这个返回的问题,我开始查找这个问题的原因,直接找 os.system() 这个函数的文档,它说明这个函数是阻塞的,等待命令执行完成才返回。那么问题应该就出现在slimerjs的脚本那里了,偶然原因,我运行那个脚本的时候忘了添加视频网页路径参数,结果它很快就返回了。因为我 window.setTimeout() 函数设置的是10毫秒,那么为什么我添加了视频网页路径之后就要等待90多秒呢,我打开了firefox的firebug,打开了那个网页。发现这个函数的时间是在所有请求加载完才开始算的。下图是firebug截图。
figure3
两个红色的请求时到了90秒才表示timeout。这是计时器开始计算,加上程序加载的时间,就是90多秒了。
那么我们自然就想到将 window.setTimeout() 函数写在打开页面外面,设定时间返回。

getPage.js

 var page = require('webpage').create();
 var videoUrl = phantom.args[0];
 window.setTimeout(function(){
     phantom.exit();
},10000);
 var page.open(videoUrl, function (){      
      window.setTimeout(function(){
            phantom.exit();
      },10);
});

最后发现这个标题不太符合这篇文章。不过还是不改了,因为我本来是按着headless browser的思想去解决这个问题的

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值