关于咪咕视频的m3u8再次解析
阅读原文时间:2023年07月08日阅读:110

软件和源码

前言

之前写过一片文章: 关于突破咪咕视频付费限制的研究, 但是后来我发现评论说已经不能用了,我知道肯定是api修改了,写这种东西就是这样,不一定什么时候就变化了,然后就用不了了,我懒得继续维护了,但是为啥我现在又发了这篇文章呢?因为我用到了我之前写的软件(也是想水一片文章),所以花点时间研究了一下这次更新后的api
这次我会详细说明过程,有兴趣的可以研究研究。

这次修改后除了付费的看不了,其它功能和原来的软件功能一样,付费的看不了可能是因为后台加入cookie认证,因为我发现访问是404。

接口

接口还是和之前的一样 https://webapi.miguvideo.com/gateway/playurl/v3/play/playurl?contId=608807416&rateType=3&startPlay=true
返回:

urlInfo": {
"urlType": "tourist",
"url": "http://h5live.gslb.cmvideo.cn/migu/kailu/20200324/cctv4meihd/50/index.m3u8?msisdn=202107310205404d3783e723ed4d848d9320848e0d6def&mdspid=&spid=699004&netType=0&sid=2200179344&pid=2028597139&timestamp=20210731020540&Channel_ID=0116_25000000-99000-100300010010001&ProgramID=608807416&ParentNodeID=-99&assertID=2200179344&client_ip=60.17.111.77&SecurityKey=20210731020540&mvid=2200179344&mcid=500020&mpid=&playurlVersion=SJ-A1-4.7.1&userid=&jmhm=&videocodec=h264&bean=mgsph5&puData=30420c934501c1ee12542c78a90a8e16",
"mediaType": "12",
"usageCode": "50",
"codeRate": "75",
"mediaSize": 0,
"rateDesc": "标清 540P",
"contId": null,

访问这个 url 发现返回的是空白,所有问题就是出在这里,正常的情况下这里应该返回一个 m3u8链接地址(在加入crossdomain=www参数后,不是标准m3u8串流格式,而是以文本形式返回的,我原来的软件中加入了crossdomain=www)。
所以关键就是解决这个问题

用浏览器打开https://www.miguvideo.com/mgs/website/prd/detail.html?cid=608807416 通过 浏览器的 开发者工具 抓包这个url 应该为 https://gslbmgsplive.miguvideo.com/migu/kailu/20200324/cctv4meihd/51/index.m3u8?msisdn=0a4020443d8d2dc2a981f89b864a9eba&mdspid=&spid=699004&netType=0&sid=2200179344&pid=2028597139&timestamp=20210731020939&Channel_ID=0132_10010001005&ProgramID=608807416&ParentNodeID=-99&assertID=2200179344&client_ip=60.17.111.77&SecurityKey=20210731020939&mvid=2200179344&mcid=500020&mpid=&playurlVersion=SJ-A1-4.7.1&userid=&jmhm=&videocodec=h264&bean=mgspwww&puData=f9178e1694798e5c9aaf409e856cdad8&ddCalcu=8fd9ea13d78c816e5186e9940749f8aea59c&crossdomain=www

我采用在其他浏览器打开这个 url 发现依然可以返回m3u8链接地址,这就说明不是 cookie 验证,那么就应该检查请求头中的差距或者请求参数上的差距。

将浏览器抓包的这个 url 与我们通过接口获得的 url 参数进行对比发现:我们抓包得到的 url 多了一个参数 ddCalcu, 我们需要知道这个是如何产生的:

遇到这种情况,肯定选择 pcPlayer.js, 而不选 带 vue(vue是js的一个框架),这种逻辑不可能在框架里。 进入后格式化js(点击左下角的**{}**),然后搜索 ddCalcu :

一下子就找到了这个函数,简单阅读其逻辑得知 参数ddCalcu 是由其它几个参数 经过这个算法得到的,到此问题几乎已经解决了,剩下的就是用 python 仿写这部分逻辑了。

python 仿写:

from urllib import parse

def ddCalcu(url):
    new_url = parse.urlparse(url)
    para = dict(parse.parse_qsl(new_url.query))
    userid = para.get("userid","")
    timestamp = para.get("timestamp","")
    ProgramID = para.get("ProgramID","")
    Channel_ID = para.get("Channel_ID","")
    puData = para.get("puData","")
    t = userid if userid else "eeeeeeeee"
    r = timestamp if timestamp else "tttttttttttttt"
    n = ProgramID if ProgramID else "ccccccccc"
    a = Channel_ID if Channel_ID else "nnnnnnnnnnnnnnnn"
    o = puData if puData else ""
    if not o:
        return url
    s = list("2624")
    u = list(t)[int(s[0])] or "e"
    l = list(r)[int(s[1])] or "t"
    c = list(n)[int(s[2])] or "c"
    f = list(a)[len(a)-int(s[3])] or "n"
    d = list(o)
    h = []
    p = 0
    while p*2 < len(d):
        h.append(d[len(d)-p-1])
        if p < len(d) - p -1:
            h.append(o[p])
        if p == 1:
            h.append(u)
        if p == 2:
            h.append(l)
        if p == 3:
            h.append(c)
        if p == 4:
            h.append(f)
        p += 1
    v = "".join(h)
    return url + "&ddCalcu=" + v

if __name__ == '__main__':
    url = "http://h5live.gslb.cmvideo.cn/migu/kailu/20200324/cctv4meihd/50/index.m3u8?msisdn=20210731022935c8b943821c7c432faed138160dd0b77f&mdspid=&spid=699004&netType=0&sid=2200179344&pid=2028597139&timestamp=20210731022935&Channel_ID=0116_25000000-99000-100300010010001&ProgramID=608807416&ParentNodeID=-99&assertID=2200179344&client_ip=60.17.111.77&SecurityKey=20210731022935&mvid=2200179344&mcid=500020&mpid=&playurlVersion=SJ-A1-4.7.1&userid=&jmhm=&videocodec=h264&bean=mgsph5&puData=4484cda45d696504453b9dc809dd5599"
    new_url = ddCalcu(url)
    print(new_url)

将从接口获得的 url地址 付给这个 url变量, 然后执行python 脚本,返回新的url, 用postman 测试一下:


发现已经可以正常返回 m3u8 url 了,问题解决, 剩下的就是将这部分逻辑整合回我原先写的软件里面,我就不详细说了。

其它

python 仿写部分:

a = Channel_ID if Channel_ID else "nnnnnnnnnnnnnnnn"

也可以这样写:

a = Channel_ID or "nnnnnnnnnnnnnnnn"

只不过我之前发现了 python 中有所谓的等价三元运算符的if else这种写法,所以想用这种写法练练手。

手机扫一扫

移动阅读更方便

阿里云服务器
腾讯云服务器
七牛云服务器