偶尔需要从cctv官网下载一些离线视频播放给学生看。我们研究一下,如何从cctv视频页面中找到下载源。
相关推荐:
之前写过一些爬虫的文章,如果你也感兴趣:
在chrome中打开任意一个cctv视频页,如 http://tv.cctv.com/2019/12/21/VIDEbqicDNVHxT2L9xbTbY9N191221.shtml,并播放页面中的视频。
打开chrome控制台,切换到 Network 面板。观察网络请求情况。

在 Type 列中,可以看到类型为 video/mp2t 的资源请求。初步猜想这便是我们要下载的视频文件。复制它的链接,在新标签页中打开。
打开后,chrome提示下载此文件。我们按它的提示来。

下载完成后,播放该文件。

我们发现,该视频文件只是整个视频的一部分(只有2.2MB大小)。所以我们进一步猜测,cctv上的视频是切成多个小文件进行连续播放的。这从图一中的 6.ts 和 7.ts 也能验证。
接下来,我们观察视频文件的url,如 6.ts 的url :http://newcntv.qcloudcdn.com/asp/hls/1200/0303000a/3/default/052fc80404db441797c3fe9592900cc1/6.ts。对于写程序的我们而言,很容易知道 052fc80404db441797c3fe9592900cc1 这串字母必定是视频文件的id。
复制该id,打开 http://tv.cctv.com/2019/12/21/VIDEbqicDNVHxT2L9xbTbY9N191221.shtml 的源码页并搜索该id。
果然,我们在源码中找到了它:

还差最后一个问题,如何知道一个完整的视频文件一共被分割成了多少份?
我从源码中没找到这个参数,不过我们可以「曲线救国」。
已知第1份视频url是后缀是 0.ts, 第二份是 1.ts。我们可以假设最大的一份是10000.ts。
访问10000.ts http://newcntv.qcloudcdn.com/asp/hls/1200/0303000a/3/default/052fc80404db441797c3fe9592900cc1/10000.ts
得到如下响应:

也就是说,我们只需要一个从0开始递增的计数器,不断循环下载文件,遇到404就结束下载。
有了以上所有信息,我们可以动手写爬虫程序了。为了方便,我这次不使用node.js,而是用shell脚本,这样更容易在终端运行。
再回顾一下整个爬虫的运行思路:
1. 得到cctv视频页面的url (如 http://tv.cctv.com/2019/12/21/VIDEbqicDNVHxT2L9xbTbY9N191221.shtml)
2. 访问该url,获得源码,并从源码中解析出视频id (guid)
3. 假设视频被切割为10000份,从0开始一直下载到10000,若中途遇到404,则提前结束
4. 将所有下载的文件合并成一个完整的视频文件
shell 代码如下:
# 下载cctv视频# 用法: cctv_video urlcctv_video(){url="$*"guid=`curl -s "$url" | sed -n '/guid = p' | sed -e 's/.*"\(.*\)".*/\1/'`f="${f:-all.ts}"for i in {0..10000}dourl=`cctv_url $guid $i`if curl --output dev/null --silent --head --fail "$url"; thenecho "$(tput setaf 46)URL exists: $url; \n开始下载(#$i)$(tput sgr0)";wget -q -O- "$url" >> "$f";elseecho "URL does not exist: $url";return 1;fidone}# 组装视频url# 用法: cctv_url guid partcctv_url(){echo "http://newcntv.qcloudcdn.com/asp/hls/1200/0303000a/3/default/${1}/${2}.ts"}
运行截图如下:

运行完成后,当前目录下会有一个 all.ts 的完整视频文件:

如此,一个完整的cctv视频爬虫就完成了。
注意,以上代码只在 macOS & zsh 5.3 (x86_64-apple-darwin18.0) 下测试过。
其它环境可能需要略微调整代码。




