paxj168 发表于 2021-10-26 19:44

清风DJ网在线播放地址JS解密转MP3方法

前面看到@ehepls 兄弟发布的易语言版,我来发一个python版的


准备工作:


1、网址:https://www.vvvdj.com/play/221250.html
2、python3.9
3、发条JS工具
4、格式工厂


1、抓包
            1-1、谷妹儿浏览器,F12
            1-2、具体内看@ehepls 兄弟发布的方法


经过分析发现,他的JS并不是独立的,而是在播放页面里面先执行,取得吗m3u8播放地址 + upt的值 + news
https://tspc.vvvdj.com/c1/2021/10/221250-bf40bf/221250.m3u8?upt=d75e43361637855999&news



2、解密

    function DeCode() {
      this.OO0O00OO00OO = function (a, b) {
            return b > 0 ? a.substring(0, b) : null;
      }, this.OO00OO0O00O0 = function (a, b) {
            return a.length - b >= 0 && a.length >= 0 && a.length - b <= a.length ? a.substring(a.length - b, a.length) : null;
      }, this.O0000OO0OO00O0 = function (a, b) {
            var c, d, e, f, g, h, i, j, k = "";
            for (c = 0; c < b.length; c++) {
                k += b.charCodeAt(c).toString();
            }
            for (d = Math.floor(k.length / 5), e = parseInt(k.charAt(d) + k.charAt(2 * d) + k.charAt(3 * d) + k.charAt(4 * d) + k.charAt(5 * d)),
                     f = Math.round(b.length / 2), g = Math.pow(2, 31) - 1, h = parseInt(a.substring(a.length - 8, a.length), 16),
                     a = a.substring(0, a.length - 8), k += h; k.length > 10; ) {
                k = (parseInt(k.substring(0, 10)) + parseInt(k.substring(10, k.length))).toString();
            }
            for (k = (e * k + f) % g, i = "", j = "", c = 0; c < a.length; c += 2) {
                i = parseInt(parseInt(a.substring(c, c + 2), 16) ^ Math.floor(255 * (k / g))), j += String.fromCharCode(i),
                  k = (e * k + f) % g;
            }
            return j;
      }, this.O0000OO0OO00O = function (a, b, c) {
            return a.length >= 0 ? a.substr(b, c) : null;
      }, this.O0O000000O0O0 = function (a) {
            return a.length;
      }, this.O000O0OO0O0OO = function (a,b) {         
            var h, i, j, k, l, m, n, o, p, c = b, d = this.O0O000000O0O0(c), e = d, f = new Array(), g = new Array();
            for (l = 1; d >= l; l++) {
                f = this.O0000OO0OO00O(c, l - 1, 1).charCodeAt(0), g = f, e -= 1;
            }
            for (h = "", i = a, m = this.OO0O00OO00OO(i, 2), i = this.OO00OO0O00O0(i, this.O0O000000O0O0(i) - 2),
                     l = 0; l < this.O0O000000O0O0(i); l += 4) {
                j = this.O0000OO0OO00O(i, l, 4), "" != j && (b = this.OO0O00OO00OO(j, 1), k = (parseInt(this.OO00OO0O00O0(j, 3)) - 100) / 3,
                  m == this.O0000OO0OO00O0("a9ab044c634a", "O0000OO0OO00O") ? (n = 2 * parseInt(b.charCodeAt(0)),
                        o = parseInt(f), p = n - o, h += String.fromCharCode(p)) : (n = 2 * parseInt(b.charCodeAt(0)),
                        o = parseInt(g), p = n - o, h += String.fromCharCode(p)));
            }
            return h;
      };
    }
    var x=new DeCode();
    playurl=x.O000O0OO0O0OO('e0>187Q190q193k196Q202N208?214m220W223_226M229o232I235j238472n475D478K484A490B499o502R5055523J526M532O535H538=541H547A556V559O571N574B57755835586Z595l601X610l613','3DVyqLyrEBCoQP9eNuqpyUEX42V4MsncH289YPId8H6tdqINVGJhi3P1sLWBLSiVQOa4LWOS8W4Q0Ha7BY7M4pDIyeX98PktWhCDvkH6JvuHpnT4fhXC6jY50SwJhKi2LKzNOypTh4th7aKdmZGbYGyJwlvnicKz1DGyF0sbF9eZknPKsHOSzBRdiHh5wG79VOi6B5tfsR0sBAMqzYgP2InT8uR08mz9UXsFGK6qNn8Ult1EOXZFGsBwj58G2NcPgxfKxWXgYMcEcx6uhlOrJ25RrPyPK7svsh8pqQWdXjvl6GVG4ZZjYq8XeDfTRJXCfJvAtKSocvxr5sNJePq6IivoX2Pe0xU47CSipsqUL9AjCwJTqkfweSjiFIzf4mT1pCJgDw9S6omu0udx3rN8kXv46IKWGrS0spAXN2mf3qpwcHDUO8bFojPlHkwtEH8iMeRhISsA4DtKsrWUPdBuCAAd0sNI3ICH4fQ0xvkBdNXE27FSyuTpaM3ZajvoH3Z2');

这上面的就是他的加密代码,具体是干了些啥,反正我也不需要理解,主要是理解不了,但不影响我们
我们只知道他的加密入口及解密参数就行了:lol:lol:lol

var x=new DeCode();
playurl=x.O000O0OO0O0OO(参数1,参数2)

先请求页面获取参数1,参数2,然后得到在带上参数请求m3u8视频流列表,知道参数怎么来的就好办了{:1_918:}

2、python3.9获取参数
需要加载几个模块
import asyncio//这个协助
import aiohttp   //这个是下载
import os   
import requests
import re
import execjs//这个是执行JS的


function DeCode() {
this.OO0O00OO00OO = function(a, b) {
    return b > 0 ? a.substring(0, b) : null;
},
this.OO00OO0O00O0 = function(a, b) {
    return a.length - b >= 0 && a.length >= 0 && a.length - b <= a.length ? a.substring(a.length - b, a.length) : null;
},
this.O0000OO0OO00O0 = function(a, b) {
    var c, d, e, f, g, h, i, j, k = "";
    for (c = 0; c < b.length; c++) {
      k += b.charCodeAt(c).toString();
    }
    for (d = Math.floor(k.length / 5), e = parseInt(k.charAt(d) + k.charAt(2 * d) + k.charAt(3 * d) + k.charAt(4 * d) + k.charAt(5 * d)), f = Math.round(b.length / 2), g = Math.pow(2, 31) - 1, h = parseInt(a.substring(a.length - 8, a.length), 16), a = a.substring(0, a.length - 8), k += h; k.length > 10;) {
      k = (parseInt(k.substring(0, 10)) + parseInt(k.substring(10, k.length))).toString();
    }
    for (k = (e * k + f) % g, i = "", j = "", c = 0; c < a.length; c += 2) {
      i = parseInt(parseInt(a.substring(c, c + 2), 16) ^ Math.floor(255 * (k / g))),
      j += String.fromCharCode(i),
      k = (e * k + f) % g;
    }
    return j;
},
this.O0000OO0OO00O = function(a, b, c) {
    return a.length >= 0 ? a.substr(b, c) : null;
},
this.O0O000000O0O0 = function(a) {
    return a.length;
},
this.O000O0OO0O0OO = function(a, b) {
    var h, i, j, k, l, m, n, o, p, c = b,
    d = this.O0O000000O0O0(c),
    e = d,
    f = new Array(),
    g = new Array();
    for (l = 1; d >= l; l++) {
      f = this.O0000OO0OO00O(c, l - 1, 1).charCodeAt(0),
      g = f,
      e -= 1;
    }
    for (h = "", i = a, m = this.OO0O00OO00OO(i, 2), i = this.OO00OO0O00O0(i, this.O0O000000O0O0(i) - 2), l = 0; l < this.O0O000000O0O0(i); l += 4) {
      j = this.O0000OO0OO00O(i, l, 4),
      "" != j && (b = this.OO0O00OO00OO(j, 1), k = (parseInt(this.OO00OO0O00O0(j, 3)) - 100) / 3, m == this.O0000OO0OO00O0("a9ab044c634a", "O0000OO0OO00O") ? (n = 2 * parseInt(b.charCodeAt(0)), o = parseInt(f), p = n - o, h += String.fromCharCode(p)) : (n = 2 * parseInt(b.charCodeAt(0)), o = parseInt(g), p = n - o, h += String.fromCharCode(p)));
    }
    return h;
};
}
function playurl(pj, pj1) {
var x = new DeCode();
playurl = x.O000O0OO0O0OO(pj, pj1);
return playurl;
}



哈哈哈,可以得到我们想要的参数,请求时候记得一定要带上 headers
带上参数请求m3u8视频流列表信息
def htmlm3u8list(htmls, headers):
    # 创建一个node对象
    node = execjs.get()
    # js源文件编译
    ctx = node.compile(open('./1-01.js', encoding='utf-8').read())
    # 执行JS涵数
    funcname = 'playurl("{0}","{1}")'.format(htmls, htmls)
    pwd = 'https:' + ctx.eval(funcname)
    tsurl = pwd.split(".m3u8")
    numbeid = tsurl.split('/')[-1]
    data = requests.get(url=pwd, headers=headers).text
    name = numbeid + "-" + htmls.replace("(", "").replace(")", "")
    print(name)
    isExists = os.path.exists(name)
    if not isExists:
      os.makedirs(name)
    tslist = re.findall(r'-\d+.ts\?upt=+', data)
    urllist = []
    for ts in tslist:
      sss = tsurl + ts
      urllist.append(sss)
    urllists = ]
    return urllists



到了这里就完成了兄弟前面的效果,但是我想把这个在加深一些,下载
下载有个问题就是,因为一个音频文件他会分成几百个流文件,如果单线程下载的话,会比较慢,然后我就用协程的方法这样快一些



async def downs(hj):
    async with aiohttp.ClientSession() as session:
      url_list = hj
      name = url_list
      print(url_list)
      print(name)
      tasks = ]
      await asyncio.wait(tasks)


async def fetch(session, urls, name):
    async with session.get(urls, verify_ssl=False) as response:
      content = await response.content.read()
      tslist = re.findall(r'-\d+.ts\?upt=+', urls)
      for ts in tslist:
            filename = ts.replace("-", "").split("?")
            print(filename)
      path = './' + name + './' + filename
      with open(path, "wb") as f:
            f.write(content)

下载的时候把ID号和文件名建一个文件夹这样方便管理
例如:221250 + 四会DJ清扬-国粤语Club抖音DjHs华少秋风吹飘来好消息串烧


好,现在流文件下载下来了,就是解决文件合并和转MP3格式了


看到一个兄弟在说在线的视频流文件很小,音质达不到要求,我们把这个问题一起解决了


网站显示的是 147.2MB   而我们下载下来的只有32.4MB,这个问题只要我们设置一下转换值就可以了
然后就是等几分钟转换好了




格式工厂比特率选择320,然后我们看一下转换后的文件是否与网站一致



一毛一样:lol:lol:lol

这个是全代码




https://tspc.vvvdj.com/c1/2021/10/221250-bf40bf/221250.m3u8?upt=d75e43361637855999&news"
https://tspc.vvvdj.com/c1/2021/10/221250-bf40bf/221250.m3u8?upt=d75e43361637855999&news

Yo丨Se7ven 发表于 2021-10-26 21:04

一个idm批量嗅探就解决了,JS解析出来的只是128k低音质的。

paxj168 发表于 2021-10-27 08:35

本帖最后由 paxj168 于 2021-10-27 08:44 编辑

yang586lin 发表于 2021-10-26 21:20
大神,请问https://m.i275.com/可以做个批量下载的工具出来吗?
我们只讨论技术,不做工具{:1_918:}

https://audiopay.cos.tx.xmcdn.com/download/1.0.0/group3/M04/BF/F5/wKgMdl4xIwnADzZaADCdnSpb3VE778.m4a?buy_key=aed65595bbd6d943057c57973f8b5b93&sign=4783c36c8d75615f8f124930695b2139&timestamp=1635295239206000&token=5360&duration=1800

wuti90 发表于 2021-10-27 08:19

igood 发表于 2021-10-26 20:51

优秀,非常不错的解析方法

A913830 发表于 2021-10-26 20:58

谢谢分享 thanks

yang586lin 发表于 2021-10-26 21:20

大神,请问https://m.i275.com/可以做个批量下载的工具出来吗?

liuyanqu929 发表于 2021-10-26 21:26

清风DJ网是我一直在用的网站,应该有十几年了。

吾爱有你更美 发表于 2021-10-26 21:38

播放的时候还是本音乐来着某某某网址

SDU123 发表于 2021-10-26 22:01

pycharm 社区版是不支持调用js文件吗?

longling 发表于 2021-10-26 22:08

感谢楼主分享               

aa361328 发表于 2021-10-26 22:16

楼主辛苦了~
页: [1] 2 3 4 5 6 7 8 9 10
查看完整版本: 清风DJ网在线播放地址JS解密转MP3方法