水族馆

一次用 python 抓取初音未来 Magical Mirai 2018 爱奇异直播流的过程

刚学 python

阅读时间 1 分钟


后记(没错后记写在开头)

2018.9.2 晚再次访问这个直播地址会重定向到 www.iqiyi.com(直播域名是 live.iqiyi.com),播放器不一样啦,上面说的都是废话啦,所以代码肯定是不能复现的,看官们看着图个乐就好。

背景

没什么特别原因,就是手痒按了下 F12 然后发现可以直接搞到直播流,然后刚学了 python 嘛,然后就想练练手嘛。

程序源码下载

https://drive.google.com/drive/folders/1cLlzk5kMoUCcMZBEdGd0PkO04PEYCFZX?usp=sharing

探究

直播地址 https://live.iqiyi.com/s/19rqq1y2if.html ,这个直播采用 Flash 播放器,用 Chrome 的开发者调试工具可以看到直播过程中,播放器在不断地用 HTTP-GET 的方式获取一串 [十六进制].data 的文件,并且每个文件之间相差了 10 的十六进制值。

经测试抓包,发现播放器在不断的 GET 这个地址

https://v-3adc3293.71edge.com/live/c16_ls_chuyin0901_720p_s10/5b8a4002.data?hl_dle=60&hl_stapp=live&hl_stid=ls_chuyin0901_720p&hl_slid=c16_ls_chuyin0901_720p_s10&qd_vip=0&hl_sttp=flv&qd_vipres=2&hl_force=0&hl_nm=6&qd_scc=103edc28149549b738ab720938e0ebe4&QY00001=1581119788&hl_stft=flv&hl_dp=NB2HI4B2F4XWM3DWNRUXMZJOOZUWIZLPFZUXC2LZNEXGG33NF4&qd_sc=3fc86db94292bce38baa5d2c0a1b8314&hl_pltp=0&hl_cid=GG2JYNZIGZ66C3G3OFTNFFTBS2GLFOWJ&qd_src=01010021010000000000&hl_slst=10&hl_cp=3&hl_dl=0&qd_ip=b73f2ff5&hl_dls=40&qd_uid=1581119788&t=1535841230_5081166029cf1529137bb89ae399bb88&hl_apptp=ppc&hl_stpt=1935&hl_stpr=http&qd_tm=1535841226844&qd_tvid=1784319323

并且视频一开始 GET 的文件是 5b8a4002.data,最后 GET 的文件是 5b8a6686.data,其他数据不变

用 python 算一下,0x5b8a6686 - 0x5b8a4002 的结果是 9870,所以一共需要下载 987 个 data 文件。

在用浏览器直接访问一下这个地址,浏览器开始自动下载 5b8a4002.data 文件,证明可以直接 GET 到这个文件。

尝试用 ffmpeg -i 5b8a4002.data,ffmpeg 告诉我 stream 0:0 是 h264 编码的 720p 视频流,stream 0:1 是 aac 编码的 256k 的音频流,用 ffplay 可以直接播放。

程序

于是编写程序,计算 5b8a4002 与 5b8a6686 的差值,每隔 10 生成一个字符串,组成一个数组用于遍历,进行下载。

下载完成后共有 987 个 data 文件,用

ffmpeg -f concat -i filelist.txt -c:v copy -c:a copy out.mp4

将所有 data 文件拼接成一个 MP4 文件。

优化

下载使用的是 urllib.request.urlopen 这个函数 (后记:不要自讨苦吃,对自己好点,请使用 requests) ,考虑到网络波动,下载可能会失败 or 连接超时,于是用 for 循环和 connection.length 来一边下载一边输出状态,出现错误捕获错误记录到 error.txt(并没有错误…)并重新调用下载函数

还要用 for 循环生成一个 filelist.txt 给 ffmpeg 拼接视频用。

考虑到断电,还要断点续传,我的操作就是下载文件前判断文件是否存在,若存在,则直接跳过并进入下一个文件的下载…不是我没事找事,是真的断电了…