js逆向爬取某音乐网站某歌手的歌曲
js逆向爬取某音乐网站某歌手的歌曲
- 一、分析网站
- 1、案例介绍
- 2、寻找列表页Ajax入口
- (1)页面展示图。
- (2)寻找部分歌曲信息Ajax的token。
- (3)寻找歌曲链接
- (4)获取歌曲名称和id信息
- 3、寻找网页数据的加密逻辑
- (1)寻找歌曲地址出处。
- (2)查找表单数据中的关键字
- (3)建立生成方法的js文件
- (4)编辑“生成构造歌曲地址的表单数据方法”的代码
- 二、开始爬取工作
- 1、构建歌曲地址
- 2、修改JS文件中的参数
- 3、成功获得歌曲链接的地址
- 三、保存并总结
一、分析网站
1、案例介绍
- 爬虫学习已经结束了,再继续练习巩固。这一次拿某音乐网站某歌星的歌曲为例,进行批量爬取。
- 这里的前端javaScript带有变量名混淆,也带有字符串混淆,还带有对象键名替换等技术,所以爬取起来,要花费一定的时间去分析并理清里面的逻辑关系。
- 这次的练习,目的很简单,思路也不麻烦,就是找到歌曲的url地址和歌曲名称,再爬取、保存。
2、寻找列表页Ajax入口
(1)页面展示图。

这里还是用右击“检查”的形式,对上面页面进行分析。虽然在“元素”这一栏能找到歌曲的链接及名字,但这次,源代码里面是找不到的,那就意味着用requests爬取不到需要的信息。
(2)寻找部分歌曲信息Ajax的token。
- 接着打开“网络”——“Fetch/XHR”,刷新之后,开始查找列表,出现很多含有“token=”的列表项,按照经验,找到“web?csrf_token=”,点击“预览”,找到想要的信息列表。如图。

- 在爬取类似歌曲信息的时候,需要注意的一点就是要关注这些列表中的id信息。
- 在“标头”栏,找到请求头“https://music.YouKnowde.com/weapi/cloudsearch/get/web?csrf_token=”,这个地址也要写入程序里面,而且看到下面的请求方法是POST方式。
- 再打开“载荷”栏,查看表单数据。如图。

上面表单数据的格式是通过加密后产生的,可以查看md5.cn网站,比较得出是哪一种加密方式。 - 先用以上信息,写一段代码,获取一部分信息,再做进一步的分析。
import requestsclass Music_Data(object):def __init__(self):super().__init__()self.url = "https://music.YouKnowde.com/weapi/cloudsearch/get/web?csrf_token="self.wangyi_url = 'https://music.YouKnowde.com/weapi/song/enhance/player/url/v1?csrf_token='self.headers = {'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/111.0.0.0 Safari/537.36','origin': 'https://music.YouKnowde.com','referer': 'https://music.YouKnowde.com/search/'}self.data = {"params": "VcB5Z4BiekLvHcWYMKc78nXTiKKCn+6eAjm8yfLksGSJr9rPpDKZP8HPJG9BYL33uYq97UL2UDkQdhq6QoKm8d+bzvJstjrmn8PDCUwE6azkPUCIhiMnCE5sonqHw8D0OGvEk0N/v3PYGqcc/Cp4HvJmrQoS50BlcA8h7X7Djcal1ku2A03QrOqT4Zkai78O4c95I5rHDxecBZbi8pvA7jji9Gf7mPmOJ1ZqaLvtsbSg+CbtyFBUWvzfQqWXKejd8hgFePlM4i/yEWb6Ug5BQg==","encSecKey": "c2dfcdf582d19c7ec069d8315befe647a0a91af398a44bb994cf69386977115df512627a4f7c4c82ec9a608fe0ea6de0e4063a4bea2a6af703615133b0b64e22adb20484dfa5db22b72866c0ab9529237cfdf9b4eaa8d67294c896de380658fa859167b67c73a35c5d65c97ba839d1a6d1feca697eedf6ef9b6bf2663fc561e3"}def get_data_index(self):resp = requests.post(url=self.url, data=self.data, headers=self.headers)print(resp.text)def run(self):self.get_data_index()if __name__ == '__main__':music = Music_Data()music.run()
- 上面代码,自然获取到了歌曲的一些信息代码。如图。

从上面获得结果看,刚才乱码形式的表单数据,可以不用理会。
(3)寻找歌曲链接
-
点击“媒体”——点击播放,看到如下结果。

-
点击这条记录,再点击“标头”栏看到请求网址信息,复制到地址栏“转到”,就能听到歌曲播放。


那么,刚才请求网址的链接,就是这首歌的播放地址。也就是说,这样就成功的找到一首歌的地址链接了。
- 然后我们看到,请求网址的地址比较乱,无规则的字符掺杂其中,那它到底是怎么来的。
(4)获取歌曲名称和id信息
- 还是在开发者工具界面,点击“网络”——“Fetch/XHR”——刷新网页并选择“web?csrf_token=”——预览,就看到字典格式的内容,用json中的方法loads改成字典格式,进一步获得歌曲名称和id信息。

- 改写程序中的get_data_index方法,由获取源代码,进一步改成获取歌曲名称和id的方法。
- 代码如下:
def get_data_index(self):resp = requests.post(url=self.url, data=self.data, headers=self.headers)# print(resp.text)# 此处根据web?csrf_token=链接汇总的预览栏,找到字典形式的信息,获取相应歌曲名dict_data = json.loads(resp.text)["result"]["songs"]# 而后遍历所有歌曲,获取name和idfor data in dict_data:name = data["name"]id = data["id"]print(name, id)- 运行之后,成功获取到想要的信息。如图。

- 运行之后,成功获取到想要的信息。如图。
3、寻找网页数据的加密逻辑
(1)寻找歌曲地址出处。
- 在上面请求网址的地址代码中,复制一小段,然后搜索即得到两个结果。如图。

经过分析,点击第二个结果的链接,再点击预览,看到下面字典格式的信息里面,就有歌曲信息的链接。如图。

再继续点开上图所示的开发者工具中的“标头”,它里面的请求网址,就是产生这首歌曲地址的请求地址。而且是以POST的请求方式。如图。

- 再按以上方式,找到一首歌曲的地址。即:媒体——播放——选中,复制一段代码搜索——找到请求网址。然后,再点“载荷”一栏,得到表单数据,也是params和encSecKey两项,不过此时的字符串变了。也就是说,换了不同的歌曲,就更换了不同的表单数据
- 显然,每次爬取歌曲,都要更换此处的表单数据,确实是挺麻烦的事。那么接下来,应该怎么做呢?
- 答案就是,表单数据是网页中JavaScript代码产生的,咱们应该继续网页表单数据中params和encSecKey两项的生成机制。即,分析明白,网页中的这一加密逻辑。
(2)查找表单数据中的关键字
- 通过如下方式,在源代码js逻辑代码中,寻找表单数据中的encSecKey的代码段。步骤如下图。

点开上面,会进入源代码里面,继续搜索“encSecKey”,会找到下图的地方,这里就是表单数据生成的代码块。

显然,上面代码中使用了字符串混淆和对象键名替换的技术。然后我们分析发现,params和encSecKey两个键对应的值里面有一个bMr1x,而bMr1x又在上面被var定义好了。再看bMr1x的定义,里面又用到了window.asrsea这个方法,接着继续搜索关键字window.asrsea,看看别处有没有定义。搜索完成,就两个结果,除了当前应用的这个地方,上面不远处,就是定义的地方。如图。

- 在这里我们发现,d就是上面定义的函数(方法),在这里给d函数断点,再播放歌曲。因为有断点,所以歌曲没有播放,马上暂停了,得到一系列参数。如图。

我们看到,上面代码中,又应用了变量名混淆的技术,变量名或函数名全部是a、b、c这样的字眼。因为我们需要的是,生成表单数据的功能,此时只要把这部分代码拿出来,形成一个js文件,就能为我所用。所以,我们复制实现这个功能的这一整个函数即可,如图。
在这里插入代码片段。
(3)建立生成方法的js文件
- 在PyCharm平台,新建一个wyy.js文件,把上面复制的JavaScript函数代码,粘贴进来,再进行适当的增删,把它的功能重建。
!function() {function a(a) {var d, e, b = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789", c = "";for (d = 0; a > d; d += 1)e = Math.random() * b.length,e = Math.floor(e),c += b.charAt(e);return c}function b(a, b) {var c = CryptoJS.enc.Utf8.parse(b), d = CryptoJS.enc.Utf8.parse("0102030405060708"), e = CryptoJS.enc.Utf8.parse(a), f = CryptoJS.AES.encrypt(e, c, {iv: d,mode: CryptoJS.mode.CBC});return f.toString()}function c(a, b, c) {var d, e;return setMaxDigits(131),d = new RSAKeyPair(b,"",c),e = encryptedString(d, a)}function d(d, e, f, g) {var h = {}, i = a(16);return h.encText = b(d, g),h.encText = b(h.encText, i),h.encSecKey = c(i, e, f),h}function e(a, b, d, e) {var f = {};return f.encText = c(a + e, b, d),f}asrsea = d
}();
-
分析上面可知,里面定义了a、b、c、d四个函数,然后运行完之后,得到四个结果。如上图右侧的红色部分。继续分析可以看出,经过混淆后,代码里面的下面这段,其中bMr1x定义完成的功能,就是上面js程序的d函数调用完成的功能。
var bMr1x = window.asrsea(JSON.stringify(i0x), bsg8Y(["流泪", "强"]), bsg8Y(TH5M.md), bsg8Y(["爱心", "女孩", "惊恐", "大笑"]));e0x.data = j0x.cr0x({params: bMr1x.encText,encSecKey: bMr1x.encSecKey -
这样,在同一个wyy.js文件里面,再写一个函数。因为上述代码里面,掺入了变量名混淆、对象键名替换等技术,仔细分析,就是一个函数调用函数,再依次返回数据(得到返回值)的过程。由此可以建立如下代码:
function start() {d:"{\"id\":\"190072\",\"c\":\"[{\\\"id\\\":\\\"190072\\\"}]\",\"csrf_token\":\"\"}"e:"010001"f:"00e0b509f6259df8642dbc35662901477df22677ec152b5ff68ace615bb7b725152b3ab17a876aea8a5aa76d2e417629ec4ee341f56135fccf695280104e0312ecbda92557c93870114af6c9d05c4f7f0c3685b7a46bee255932575cce10b424d813cfe4875d3e82047b97ddef52741d546b8e289dc6935b3ece0462db0a22b8e7"g:"0CoJUm6Qyw8W8jud"var bMr1x = asrsea(JSON.stringify(d),e,f,g)return bMr1x } -
上面两段代码,是从网页源代码中剥离出来,放到wyy.js里面,对函数内部运作方法稍加分析之后,重新整理合适的代码,整个wyy.js代码改成如下形式:
!function() {function a(a) {var d, e, b = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789", c = "";for (d = 0; a > d; d += 1)e = Math.random() * b.length,e = Math.floor(e),c += b.charAt(e);return c}function b(a, b) {var c = CryptoJS.enc.Utf8.parse(b), d = CryptoJS.enc.Utf8.parse("0102030405060708"), e = CryptoJS.enc.Utf8.parse(a), f = CryptoJS.AES.encrypt(e, c, {iv: d,mode: CryptoJS.mode.CBC});return f.toString()}function c(a, b, c) {var d, e;return setMaxDigits(131),d = new RSAKeyPair(b,"",c),e = encryptedString(d, a)}function d(d, e, f, g) {var h = {}, i = a(16);return h.encText = b(d, g),h.encText = b(h.encText, i),h.encSecKey = c(i, e, f),h}function e(a, b, d, e) {var f = {};return f.encText = c(a + e, b, d),f}asrsea = d
}();function start() {var d = {"ids":"[1894007406]","level":"standard","encodeType":"aac","csrf_token":""}var e = "010001"var f = "00e0b509f6259df8642dbc35662901477df22677ec152b5ff68ace615bb7b725152b3ab17a876aea8a5aa76d2e417629ec4ee341f56135fccf695280104e0312ecbda92557c93870114af6c9d05c4f7f0c3685b7a46bee255932575cce10b424d813cfe4875d3e82047b97ddef52741d546b8e289dc6935b3ece0462db0a22b8e7"var g = "0CoJUm6Qyw8W8jud"var bMr1x = asrsea(JSON.stringify(d),e,f,g)return bMr1x
}
(4)编辑“生成构造歌曲地址的表单数据方法”的代码
- 上面得到了歌曲名称和id,下面就构建歌曲地址。在程序中,重新定义一个函数get_music_url_index,然后运行。

- 上面的代码运行后,得到错误。这是因为前面的wyy.js中有一个函数变量,没有写入wyy.js程序中,还有下面的setMaxDigits等函数,如图黄色方框内的方法。

- 因此索性,把CryptoJS开头定义的代码,一直复制到与前面函数交界的地方。这里有个技巧,选择就容易许多。就是在源代码中的下方,有一队大括号{},点击一下,一个函数的代码就收缩起来,此处选择三个方法CryptoJS、RSAKeyPair和encryptedString,正好和前面d函数所在的函数紧挨着。选择好之后,复制粘贴到wyy.js的开端。整个代码如下:
var CryptoJS=CryptoJS||function(u,p){var d={},l=d.lib={},s=function(){},t=l.Base={extend:function(a){s.prototype=this;var c=new s;a&&c.mixIn(a);c.hasOwnProperty("init")||(c.init=function(){c.$super.init.apply(this,arguments)});c.init.prototype=c;c.$super=this;return c},create:function(){var a=this.extend();a.init.apply(a,arguments);return a},init:function(){},mixIn:function(a){for(var c in a)a.hasOwnProperty(c)&&(this[c]=a[c]);a.hasOwnProperty("toString")&&(this.toString=a.toString)},clone:function(){return this.init.prototype.extend(this)}},r=l.WordArray=t.extend({init:function(a,c){a=this.words=a||[];this.sigBytes=c!=p?c:4*a.length},toString:function(a){return(a||v).stringify(this)},concat:function(a){var c=this.words,e=a.words,j=this.sigBytes;a=a.sigBytes;this.clamp();if(j%4)for(var k=0;k<a;k++)c[j+k>>>2]|=(e[k>>>2]>>>24-8*(k%4)&255)<<24-8*((j+k)%4);else if(65535<e.length)for(k=0;k<a;k+=4)c[j+k>>>2]=e[k>>>2];else c.push.apply(c,e);this.sigBytes+=a;return this},clamp:function(){var a=this.words,c=this.sigBytes;a[c>>>2]&=4294967295<<32-8*(c%4);a.length=u.ceil(c/4)},clone:function(){var a=t.clone.call(this);a.words=this.words.slice(0);return a},random:function(a){for(var c=[],e=0;e<a;e+=4)c.push(4294967296*u.random()|0);return new r.init(c,a)}}),w=d.enc={},v=w.Hex={stringify:function(a){var c=a.words;a=a.sigBytes;for(var e=[],j=0;j<a;j++){var k=c[j>>>2]>>>24-8*(j%4)&255;e.push((k>>>4).toString(16));e.push((k&15).toString(16))}return e.join("")},parse:function(a){for(var c=a.length,e=[],j=0;j<c;j+=2)e[j>>>3]|=parseInt(a.substr(j,2),16)<<24-4*(j%8);return new r.init(e,c/2)}},b=w.Latin1={stringify:function(a){var c=a.words;a=a.sigBytes;for(var e=[],j=0;j<a;j++)e.push(String.fromCharCode(c[j>>>2]>>>24-8*(j%4)&255));return e.join("")},parse:function(a){for(var c=a.length,e=[],j=0;j<c;j++)e[j>>>2]|=(a.charCodeAt(j)&255)<<24-8*(j%4);return new r.init(e,c)}},x=w.Utf8={stringify:function(a){try{return decodeURIComponent(escape(b.stringify(a)))}catch(c){throw Error("Malformed UTF-8 data")}},parse:function(a){return b.parse(unescape(encodeURIComponent(a)))}},q=l.BufferedBlockAlgorithm=t.extend({reset:function(){this.i0x=new r.init;this.yE7x=0},Ap8h:function(a){"string"==typeof a&&(a=x.parse(a));this.i0x.concat(a);this.yE7x+=a.sigBytes},mD4H:function(a){var c=this.i0x,e=c.words,j=c.sigBytes,k=this.blockSize,b=j/(4*k),b=a?u.ceil(b):u.max((b|0)-this.UZ5e,0);a=b*k;j=u.min(4*a,j);if(a){for(var q=0;q<a;q+=k)this.tt6n(e,q);q=e.splice(0,a);c.sigBytes-=j}return new r.init(q,j)},clone:function(){var a=t.clone.call(this);a.i0x=this.i0x.clone();return a},UZ5e:0});l.Hasher=q.extend({cfg:t.extend(),init:function(a){this.cfg=this.cfg.extend(a);this.reset()},reset:function(){q.reset.call(this);this.mk4o()},update:function(a){this.Ap8h(a);this.mD4H();return this},finalize:function(a){a&&this.Ap8h(a);return this.nZ4d()},blockSize:16,mO4S:function(a){return function(b,e){return(new a.init(e)).finalize(b)}},yD7w:function(a){return function(b,e){return(new n.HMAC.init(a,e)).finalize(b)}}});var n=d.algo={};return d}(Math);(function(){var u=CryptoJS,p=u.lib.WordArray;u.enc.Base64={stringify:function(d){var l=d.words,p=d.sigBytes,t=this.bD0x;d.clamp();d=[];for(var r=0;r<p;r+=3)for(var w=(l[r>>>2]>>>24-8*(r%4)&255)<<16|(l[r+1>>>2]>>>24-8*((r+1)%4)&255)<<8|l[r+2>>>2]>>>24-8*((r+2)%4)&255,v=0;4>v&&r+.75*v<p;v++)d.push(t.charAt(w>>>6*(3-v)&63));if(l=t.charAt(64))for(;d.length%4;)d.push(l);return d.join("")},parse:function(d){var l=d.length,s=this.bD0x,t=s.charAt(64);t&&(t=d.indexOf(t),-1!=t&&(l=t));for(var t=[],r=0,w=0;w<l;w++)if(w%4){var v=s.indexOf(d.charAt(w-1))<<2*(w%4),b=s.indexOf(d.charAt(w))>>>6-2*(w%4);t[r>>>2]|=(v|b)<<24-8*(r%4);r++}return p.create(t,r)},bD0x:"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="}})();(function(u){function p(b,n,a,c,e,j,k){b=b+(n&a|~n&c)+e+k;return(b<<j|b>>>32-j)+n}function d(b,n,a,c,e,j,k){b=b+(n&c|a&~c)+e+k;return(b<<j|b>>>32-j)+n}function l(b,n,a,c,e,j,k){b=b+(n^a^c)+e+k;return(b<<j|b>>>32-j)+n}function s(b,n,a,c,e,j,k){b=b+(a^(n|~c))+e+k;return(b<<j|b>>>32-j)+n}for(var t=CryptoJS,r=t.lib,w=r.WordArray,v=r.Hasher,r=t.algo,b=[],x=0;64>x;x++)b[x]=4294967296*u.abs(u.sin(x+1))|0;r=r.MD5=v.extend({mk4o:function(){this.cT1x=new w.init([1732584193,4023233417,2562383102,271733878])},tt6n:function(q,n){for(var a=0;16>a;a++){var c=n+a,e=q[c];q[c]=(e<<8|e>>>24)&16711935|(e<<24|e>>>8)&4278255360}var a=this.cT1x.words,c=q[n+0],e=q[n+1],j=q[n+2],k=q[n+3],z=q[n+4],r=q[n+5],t=q[n+6],w=q[n+7],v=q[n+8],A=q[n+9],B=q[n+10],C=q[n+11],u=q[n+12],D=q[n+13],E=q[n+14],x=q[n+15],f=a[0],m=a[1],g=a[2],h=a[3],f=p(f,m,g,h,c,7,b[0]),h=p(h,f,m,g,e,12,b[1]),g=p(g,h,f,m,j,17,b[2]),m=p(m,g,h,f,k,22,b[3]),f=p(f,m,g,h,z,7,b[4]),h=p(h,f,m,g,r,12,b[5]),g=p(g,h,f,m,t,17,b[6]),m=p(m,g,h,f,w,22,b[7]),f=p(f,m,g,h,v,7,b[8]),h=p(h,f,m,g,A,12,b[9]),g=p(g,h,f,m,B,17,b[10]),m=p(m,g,h,f,C,22,b[11]),f=p(f,m,g,h,u,7,b[12]),h=p(h,f,m,g,D,12,b[13]),g=p(g,h,f,m,E,17,b[14]),m=p(m,g,h,f,x,22,b[15]),f=d(f,m,g,h,e,5,b[16]),h=d(h,f,m,g,t,9,b[17]),g=d(g,h,f,m,C,14,b[18]),m=d(m,g,h,f,c,20,b[19]),f=d(f,m,g,h,r,5,b[20]),h=d(h,f,m,g,B,9,b[21]),g=d(g,h,f,m,x,14,b[22]),m=d(m,g,h,f,z,20,b[23]),f=d(f,m,g,h,A,5,b[24]),h=d(h,f,m,g,E,9,b[25]),g=d(g,h,f,m,k,14,b[26]),m=d(m,g,h,f,v,20,b[27]),f=d(f,m,g,h,D,5,b[28]),h=d(h,f,m,g,j,9,b[29]),g=d(g,h,f,m,w,14,b[30]),m=d(m,g,h,f,u,20,b[31]),f=l(f,m,g,h,r,4,b[32]),h=l(h,f,m,g,v,11,b[33]),g=l(g,h,f,m,C,16,b[34]),m=l(m,g,h,f,E,23,b[35]),f=l(f,m,g,h,e,4,b[36]),h=l(h,f,m,g,z,11,b[37]),g=l(g,h,f,m,w,16,b[38]),m=l(m,g,h,f,B,23,b[39]),f=l(f,m,g,h,D,4,b[40]),h=l(h,f,m,g,c,11,b[41]),g=l(g,h,f,m,k,16,b[42]),m=l(m,g,h,f,t,23,b[43]),f=l(f,m,g,h,A,4,b[44]),h=l(h,f,m,g,u,11,b[45]),g=l(g,h,f,m,x,16,b[46]),m=l(m,g,h,f,j,23,b[47]),f=s(f,m,g,h,c,6,b[48]),h=s(h,f,m,g,w,10,b[49]),g=s(g,h,f,m,E,15,b[50]),m=s(m,g,h,f,r,21,b[51]),f=s(f,m,g,h,u,6,b[52]),h=s(h,f,m,g,k,10,b[53]),g=s(g,h,f,m,B,15,b[54]),m=s(m,g,h,f,e,21,b[55]),f=s(f,m,g,h,v,6,b[56]),h=s(h,f,m,g,x,10,b[57]),g=s(g,h,f,m,t,15,b[58]),m=s(m,g,h,f,D,21,b[59]),f=s(f,m,g,h,z,6,b[60]),h=s(h,f,m,g,C,10,b[61]),g=s(g,h,f,m,j,15,b[62]),m=s(m,g,h,f,A,21,b[63]);a[0]=a[0]+f|0;a[1]=a[1]+m|0;a[2]=a[2]+g|0;a[3]=a[3]+h|0},nZ4d:function(){var b=this.i0x,n=b.words,a=8*this.yE7x,c=8*b.sigBytes;n[c>>>5]|=128<<24-c%32;var e=u.floor(a/4294967296);n[(c+64>>>9<<4)+15]=(e<<8|e>>>24)&16711935|(e<<24|e>>>8)&4278255360;n[(c+64>>>9<<4)+14]=(a<<8|a>>>24)&16711935|(a<<24|a>>>8)&4278255360;b.sigBytes=4*(n.length+1);this.mD4H();b=this.cT1x;n=b.words;for(a=0;4>a;a++)c=n[a],n[a]=(c<<8|c>>>24)&16711935|(c<<24|c>>>8)&4278255360;return b},clone:function(){var b=v.clone.call(this);b.cT1x=this.cT1x.clone();return b}});t.MD5=v.mO4S(r);t.HmacMD5=v.yD7w(r)})(Math);(function(){var u=CryptoJS,p=u.lib,d=p.Base,l=p.WordArray,p=u.algo,s=p.EvpKDF=d.extend({cfg:d.extend({keySize:4,hasher:p.MD5,iterations:1}),init:function(d){this.cfg=this.cfg.extend(d)},compute:function(d,r){for(var p=this.cfg,s=p.hasher.create(),b=l.create(),u=b.words,q=p.keySize,p=p.iterations;u.length<q;){n&&s.update(n);var n=s.update(d).finalize(r);s.reset();for(var a=1;a<p;a++)n=s.finalize(n),s.reset();b.concat(n)}b.sigBytes=4*q;return b}});u.EvpKDF=function(d,l,p){return s.create(p).compute(d,l)}})();CryptoJS.lib.Cipher||function(u){var p=CryptoJS,d=p.lib,l=d.Base,s=d.WordArray,t=d.BufferedBlockAlgorithm,r=p.enc.Base64,w=p.algo.EvpKDF,v=d.Cipher=t.extend({cfg:l.extend(),createEncryptor:function(e,a){return this.create(this.If2x,e,a)},createDecryptor:function(e,a){return this.create(this.brx8p,e,a)},init:function(e,a,b){this.cfg=this.cfg.extend(b);this.UA5F=e;this.J0x=a;this.reset()},reset:function(){t.reset.call(this);this.mk4o()},process:function(e){this.Ap8h(e);return this.mD4H()},finalize:function(e){e&&this.Ap8h(e);return this.nZ4d()},keySize:4,ivSize:4,If2x:1,brx8p:2,mO4S:function(e){return{encrypt:function(b,k,d){return("string"==typeof k?c:a).encrypt(e,b,k,d)},decrypt:function(b,k,d){return("string"==typeof k?c:a).decrypt(e,b,k,d)}}}});d.StreamCipher=v.extend({nZ4d:function(){return this.mD4H(!0)},blockSize:1});var b=p.mode={},x=function(e,a,b){var c=this.tC6w;c?this.tC6w=u:c=this.DV9M;for(var d=0;d<b;d++)e[a+d]^=c[d]},q=(d.BlockCipherMode=l.extend({createEncryptor:function(e,a){return this.Encryptor.create(e,a)},createDecryptor:function(e,a){return this.Decryptor.create(e,a)},init:function(e,a){this.ua6U=e;this.tC6w=a}})).extend();q.Encryptor=q.extend({processBlock:function(e,a){var b=this.ua6U,c=b.blockSize;x.call(this,e,a,c);b.encryptBlock(e,a);this.DV9M=e.slice(a,a+c)}});q.Decryptor=q.extend({processBlock:function(e,a){var b=this.ua6U,c=b.blockSize,d=e.slice(a,a+c);b.decryptBlock(e,a);x.call(this,e,a,c);this.DV9M=d}});b=b.CBC=q;q=(p.pad={}).Pkcs7={pad:function(a,b){for(var c=4*b,c=c-a.sigBytes%c,d=c<<24|c<<16|c<<8|c,l=[],n=0;n<c;n+=4)l.push(d);c=s.create(l,c);a.concat(c)},unpad:function(a){a.sigBytes-=a.words[a.sigBytes-1>>>2]&255}};d.BlockCipher=v.extend({cfg:v.cfg.extend({mode:b,padding:q}),reset:function(){v.reset.call(this);var a=this.cfg,b=a.iv,a=a.mode;if(this.UA5F==this.If2x)var c=a.createEncryptor;else c=a.createDecryptor,this.UZ5e=1;this.eR1x=c.call(a,this,b&&b.words)},tt6n:function(a,b){this.eR1x.processBlock(a,b)},nZ4d:function(){var a=this.cfg.padding;if(this.UA5F==this.If2x){a.pad(this.i0x,this.blockSize);var b=this.mD4H(!0)}else b=this.mD4H(!0),a.unpad(b);return b},blockSize:4});var n=d.CipherParams=l.extend({init:function(a){this.mixIn(a)},toString:function(a){return(a||this.formatter).stringify(this)}}),b=(p.format={}).OpenSSL={stringify:function(a){var b=a.ciphertext;a=a.salt;return(a?s.create([1398893684,1701076831]).concat(a).concat(b):b).toString(r)},parse:function(a){a=r.parse(a);var b=a.words;if(1398893684==b[0]&&1701076831==b[1]){var c=s.create(b.slice(2,4));b.splice(0,4);a.sigBytes-=16}return n.create({ciphertext:a,salt:c})}},a=d.SerializableCipher=l.extend({cfg:l.extend({format:b}),encrypt:function(a,b,c,d){d=this.cfg.extend(d);var l=a.createEncryptor(c,d);b=l.finalize(b);l=l.cfg;return n.create({ciphertext:b,key:c,iv:l.iv,algorithm:a,mode:l.mode,padding:l.padding,blockSize:a.blockSize,formatter:d.format})},decrypt:function(a,b,c,d){d=this.cfg.extend(d);b=this.HX2x(b,d.format);return a.createDecryptor(c,d).finalize(b.ciphertext)},HX2x:function(a,b){return"string"==typeof a?b.parse(a,this):a}}),p=(p.kdf={}).OpenSSL={execute:function(a,b,c,d){d||(d=s.random(8));a=w.create({keySize:b+c}).compute(a,d);c=s.create(a.words.slice(b),4*c);a.sigBytes=4*b;return n.create({key:a,iv:c,salt:d})}},c=d.PasswordBasedCipher=a.extend({cfg:a.cfg.extend({kdf:p}),encrypt:function(b,c,d,l){l=this.cfg.extend(l);d=l.kdf.execute(d,b.keySize,b.ivSize);l.iv=d.iv;b=a.encrypt.call(this,b,c,d.key,l);b.mixIn(d);return b},decrypt:function(b,c,d,l){l=this.cfg.extend(l);c=this.HX2x(c,l.format);d=l.kdf.execute(d,b.keySize,b.ivSize,c.salt);l.iv=d.iv;return a.decrypt.call(this,b,c,d.key,l)}})}();(function(){for(var u=CryptoJS,p=u.lib.BlockCipher,d=u.algo,l=[],s=[],t=[],r=[],w=[],v=[],b=[],x=[],q=[],n=[],a=[],c=0;256>c;c++)a[c]=128>c?c<<1:c<<1^283;for(var e=0,j=0,c=0;256>c;c++){var k=j^j<<1^j<<2^j<<3^j<<4,k=k>>>8^k&255^99;l[e]=k;s[k]=e;var z=a[e],F=a[z],G=a[F],y=257*a[k]^16843008*k;t[e]=y<<24|y>>>8;r[e]=y<<16|y>>>16;w[e]=y<<8|y>>>24;v[e]=y;y=16843009*G^65537*F^257*z^16843008*e;b[k]=y<<24|y>>>8;x[k]=y<<16|y>>>16;q[k]=y<<8|y>>>24;n[k]=y;e?(e=z^a[a[a[G^z]]],j^=a[a[j]]):e=j=1}var H=[0,1,2,4,8,16,32,64,128,27,54],d=d.AES=p.extend({mk4o:function(){for(var a=this.J0x,c=a.words,d=a.sigBytes/4,a=4*((this.bgi6c=d+6)+1),e=this.brW8O=[],j=0;j<a;j++)if(j<d)e[j]=c[j];else{var k=e[j-1];j%d?6<d&&4==j%d&&(k=l[k>>>24]<<24|l[k>>>16&255]<<16|l[k>>>8&255]<<8|l[k&255]):(k=k<<8|k>>>24,k=l[k>>>24]<<24|l[k>>>16&255]<<16|l[k>>>8&255]<<8|l[k&255],k^=H[j/d|0]<<24);e[j]=e[j-d]^k}c=this.bse8W=[];for(d=0;d<a;d++)j=a-d,k=d%4?e[j]:e[j-4],c[d]=4>d||4>=j?k:b[l[k>>>24]]^x[l[k>>>16&255]]^q[l[k>>>8&255]]^n[l[k&255]]},encryptBlock:function(a,b){this.DW9N(a,b,this.brW8O,t,r,w,v,l)},decryptBlock:function(a,c){var d=a[c+1];a[c+1]=a[c+3];a[c+3]=d;this.DW9N(a,c,this.bse8W,b,x,q,n,s);d=a[c+1];a[c+1]=a[c+3];a[c+3]=d},DW9N:function(a,b,c,d,e,j,l,f){for(var m=this.bgi6c,g=a[b]^c[0],h=a[b+1]^c[1],k=a[b+2]^c[2],n=a[b+3]^c[3],p=4,r=1;r<m;r++)var q=d[g>>>24]^e[h>>>16&255]^j[k>>>8&255]^l[n&255]^c[p++],s=d[h>>>24]^e[k>>>16&255]^j[n>>>8&255]^l[g&255]^c[p++],t=d[k>>>24]^e[n>>>16&255]^j[g>>>8&255]^l[h&255]^c[p++],n=d[n>>>24]^e[g>>>16&255]^j[h>>>8&255]^l[k&255]^c[p++],g=q,h=s,k=t;q=(f[g>>>24]<<24|f[h>>>16&255]<<16|f[k>>>8&255]<<8|f[n&255])^c[p++];s=(f[h>>>24]<<24|f[k>>>16&255]<<16|f[n>>>8&255]<<8|f[g&255])^c[p++];t=(f[k>>>24]<<24|f[n>>>16&255]<<16|f[g>>>8&255]<<8|f[h&255])^c[p++];n=(f[n>>>24]<<24|f[g>>>16&255]<<16|f[h>>>8&255]<<8|f[k&255])^c[p++];a[b]=q;a[b+1]=s;a[b+2]=t;a[b+3]=n},keySize:8});u.AES=p.mO4S(d)})(); function RSAKeyPair(a,b,c){this.e=biFromHex(a),this.d=biFromHex(b),this.m=biFromHex(c),this.chunkSize=2*biHighIndex(this.m),this.radix=16,this.barrett=new BarrettMu(this.m)}function twoDigit(a){return(10>a?"0":"")+String(a)}function encryptedString(a,b){for(var f,g,h,i,j,k,l,c=new Array,d=b.length,e=0;d>e;)c[e]=b.charCodeAt(e),e++;for(;0!=c.length%a.chunkSize;)c[e++]=0;for(f=c.length,g="",e=0;f>e;e+=a.chunkSize){for(j=new BigInt,h=0,i=e;i<e+a.chunkSize;++h)j.digits[h]=c[i++],j.digits[h]+=c[i++]<<8;k=a.barrett.powMod(j,a.e),l=16==a.radix?biToHex(k):biToString(k,a.radix),g+=l+" "}return g.substring(0,g.length-1)}function decryptedString(a,b){var e,f,g,h,c=b.split(" "),d="";for(e=0;e<c.length;++e)for(h=16==a.radix?biFromHex(c[e]):biFromString(c[e],a.radix),g=a.barrett.powMod(h,a.d),f=0;f<=biHighIndex(g);++f)d+=String.fromCharCode(255&g.digits[f],g.digits[f]>>8);return 0==d.charCodeAt(d.length-1)&&(d=d.substring(0,d.length-1)),d}function setMaxDigits(a){maxDigits=a,ZERO_ARRAY=new Array(maxDigits);for(var b=0;b<ZERO_ARRAY.length;b++)ZERO_ARRAY[b]=0;bigZero=new BigInt,bigOne=new BigInt,bigOne.digits[0]=1}function BigInt(a){this.digits="boolean"==typeof a&&1==a?null:ZERO_ARRAY.slice(0),this.isNeg=!1}function biFromDecimal(a){for(var d,e,f,b="-"==a.charAt(0),c=b?1:0;c<a.length&&"0"==a.charAt(c);)++c;if(c==a.length)d=new BigInt;else{for(e=a.length-c,f=e%dpl10,0==f&&(f=dpl10),d=biFromNumber(Number(a.substr(c,f))),c+=f;c<a.length;)d=biAdd(biMultiply(d,lr10),biFromNumber(Number(a.substr(c,dpl10)))),c+=dpl10;d.isNeg=b}return d}function biCopy(a){var b=new BigInt(!0);return b.digits=a.digits.slice(0),b.isNeg=a.isNeg,b}function biFromNumber(a){var c,b=new BigInt;for(b.isNeg=0>a,a=Math.abs(a),c=0;a>0;)b.digits[c++]=a&maxDigitVal,a>>=biRadixBits;return b}function reverseStr(a){var c,b="";for(c=a.length-1;c>-1;--c)b+=a.charAt(c);return b}function biToString(a,b){var d,e,c=new BigInt;for(c.digits[0]=b,d=biDivideModulo(a,c),e=hexatrigesimalToChar[d[1].digits[0]];1==biCompare(d[0],bigZero);)d=biDivideModulo(d[0],c),digit=d[1].digits[0],e+=hexatrigesimalToChar[d[1].digits[0]];return(a.isNeg?"-":"")+reverseStr(e)}function biToDecimal(a){var c,d,b=new BigInt;for(b.digits[0]=10,c=biDivideModulo(a,b),d=String(c[1].digits[0]);1==biCompare(c[0],bigZero);)c=biDivideModulo(c[0],b),d+=String(c[1].digits[0]);return(a.isNeg?"-":"")+reverseStr(d)}function digitToHex(a){var b=15,c="";for(i=0;4>i;++i)c+=hexToChar[a&b],a>>>=4;return reverseStr(c)}function biToHex(a){var d,b="";for(biHighIndex(a),d=biHighIndex(a);d>-1;--d)b+=digitToHex(a.digits[d]);return b}function charToHex(a){var h,b=48,c=b+9,d=97,e=d+25,f=65,g=90;return h=a>=b&&c>=a?a-b:a>=f&&g>=a?10+a-f:a>=d&&e>=a?10+a-d:0}function hexToDigit(a){var d,b=0,c=Math.min(a.length,4);for(d=0;c>d;++d)b<<=4,b|=charToHex(a.charCodeAt(d));return b}function biFromHex(a){var d,e,b=new BigInt,c=a.length;for(d=c,e=0;d>0;d-=4,++e)b.digits[e]=hexToDigit(a.substr(Math.max(d-4,0),Math.min(d,4)));return b}function biFromString(a,b){var g,h,i,j,c="-"==a.charAt(0),d=c?1:0,e=new BigInt,f=new BigInt;for(f.digits[0]=1,g=a.length-1;g>=d;g--)h=a.charCodeAt(g),i=charToHex(h),j=biMultiplyDigit(f,i),e=biAdd(e,j),f=biMultiplyDigit(f,b);return e.isNeg=c,e}function biDump(a){return(a.isNeg?"-":"")+a.digits.join(" ")}function biAdd(a,b){var c,d,e,f;if(a.isNeg!=b.isNeg)b.isNeg=!b.isNeg,c=biSubtract(a,b),b.isNeg=!b.isNeg;else{for(c=new BigInt,d=0,f=0;f<a.digits.length;++f)e=a.digits[f]+b.digits[f]+d,c.digits[f]=65535&e,d=Number(e>=biRadix);c.isNeg=a.isNeg}return c}function biSubtract(a,b){var c,d,e,f;if(a.isNeg!=b.isNeg)b.isNeg=!b.isNeg,c=biAdd(a,b),b.isNeg=!b.isNeg;else{for(c=new BigInt,e=0,f=0;f<a.digits.length;++f)d=a.digits[f]-b.digits[f]+e,c.digits[f]=65535&d,c.digits[f]<0&&(c.digits[f]+=biRadix),e=0-Number(0>d);if(-1==e){for(e=0,f=0;f<a.digits.length;++f)d=0-c.digits[f]+e,c.digits[f]=65535&d,c.digits[f]<0&&(c.digits[f]+=biRadix),e=0-Number(0>d);c.isNeg=!a.isNeg}else c.isNeg=a.isNeg}return c}function biHighIndex(a){for(var b=a.digits.length-1;b>0&&0==a.digits[b];)--b;return b}function biNumBits(a){var e,b=biHighIndex(a),c=a.digits[b],d=(b+1)*bitsPerDigit;for(e=d;e>d-bitsPerDigit&&0==(32768&c);--e)c<<=1;return e}function biMultiply(a,b){var d,h,i,k,c=new BigInt,e=biHighIndex(a),f=biHighIndex(b);for(k=0;f>=k;++k){for(d=0,i=k,j=0;e>=j;++j,++i)h=c.digits[i]+a.digits[j]*b.digits[k]+d,c.digits[i]=h&maxDigitVal,d=h>>>biRadixBits;c.digits[k+e+1]=d}return c.isNeg=a.isNeg!=b.isNeg,c}function biMultiplyDigit(a,b){var c,d,e,f;for(result=new BigInt,c=biHighIndex(a),d=0,f=0;c>=f;++f)e=result.digits[f]+a.digits[f]*b+d,result.digits[f]=e&maxDigitVal,d=e>>>biRadixBits;return result.digits[1+c]=d,result}function arrayCopy(a,b,c,d,e){var g,h,f=Math.min(b+e,a.length);for(g=b,h=d;f>g;++g,++h)c[h]=a[g]}function biShiftLeft(a,b){var e,f,g,h,c=Math.floor(b/bitsPerDigit),d=new BigInt;for(arrayCopy(a.digits,0,d.digits,c,d.digits.length-c),e=b%bitsPerDigit,f=bitsPerDigit-e,g=d.digits.length-1,h=g-1;g>0;--g,--h)d.digits[g]=d.digits[g]<<e&maxDigitVal|(d.digits[h]&highBitMasks[e])>>>f;return d.digits[0]=d.digits[g]<<e&maxDigitVal,d.isNeg=a.isNeg,d}function biShiftRight(a,b){var e,f,g,h,c=Math.floor(b/bitsPerDigit),d=new BigInt;for(arrayCopy(a.digits,c,d.digits,0,a.digits.length-c),e=b%bitsPerDigit,f=bitsPerDigit-e,g=0,h=g+1;g<d.digits.length-1;++g,++h)d.digits[g]=d.digits[g]>>>e|(d.digits[h]&lowBitMasks[e])<<f;return d.digits[d.digits.length-1]>>>=e,d.isNeg=a.isNeg,d}function biMultiplyByRadixPower(a,b){var c=new BigInt;return arrayCopy(a.digits,0,c.digits,b,c.digits.length-b),c}function biDivideByRadixPower(a,b){var c=new BigInt;return arrayCopy(a.digits,b,c.digits,0,c.digits.length-b),c}function biModuloByRadixPower(a,b){var c=new BigInt;return arrayCopy(a.digits,0,c.digits,0,b),c}function biCompare(a,b){if(a.isNeg!=b.isNeg)return 1-2*Number(a.isNeg);for(var c=a.digits.length-1;c>=0;--c)if(a.digits[c]!=b.digits[c])return a.isNeg?1-2*Number(a.digits[c]>b.digits[c]):1-2*Number(a.digits[c]<b.digits[c]);return 0}function biDivideModulo(a,b){var f,g,h,i,j,k,l,m,n,o,p,q,r,s,c=biNumBits(a),d=biNumBits(b),e=b.isNeg;if(d>c)return a.isNeg?(f=biCopy(bigOne),f.isNeg=!b.isNeg,a.isNeg=!1,b.isNeg=!1,g=biSubtract(b,a),a.isNeg=!0,b.isNeg=e):(f=new BigInt,g=biCopy(a)),new Array(f,g);for(f=new BigInt,g=a,h=Math.ceil(d/bitsPerDigit)-1,i=0;b.digits[h]<biHalfRadix;)b=biShiftLeft(b,1),++i,++d,h=Math.ceil(d/bitsPerDigit)-1;for(g=biShiftLeft(g,i),c+=i,j=Math.ceil(c/bitsPerDigit)-1,k=biMultiplyByRadixPower(b,j-h);-1!=biCompare(g,k);)++f.digits[j-h],g=biSubtract(g,k);for(l=j;l>h;--l){for(m=l>=g.digits.length?0:g.digits[l],n=l-1>=g.digits.length?0:g.digits[l-1],o=l-2>=g.digits.length?0:g.digits[l-2],p=h>=b.digits.length?0:b.digits[h],q=h-1>=b.digits.length?0:b.digits[h-1],f.digits[l-h-1]=m==p?maxDigitVal:Math.floor((m*biRadix+n)/p),r=f.digits[l-h-1]*(p*biRadix+q),s=m*biRadixSquared+(n*biRadix+o);r>s;)--f.digits[l-h-1],r=f.digits[l-h-1]*(p*biRadix|q),s=m*biRadix*biRadix+(n*biRadix+o);k=biMultiplyByRadixPower(b,l-h-1),g=biSubtract(g,biMultiplyDigit(k,f.digits[l-h-1])),g.isNeg&&(g=biAdd(g,k),--f.digits[l-h-1])}return g=biShiftRight(g,i),f.isNeg=a.isNeg!=e,a.isNeg&&(f=e?biAdd(f,bigOne):biSubtract(f,bigOne),b=biShiftRight(b,i),g=biSubtract(b,g)),0==g.digits[0]&&0==biHighIndex(g)&&(g.isNeg=!1),new Array(f,g)}function biDivide(a,b){return biDivideModulo(a,b)[0]}function biModulo(a,b){return biDivideModulo(a,b)[1]}function biMultiplyMod(a,b,c){return biModulo(biMultiply(a,b),c)}function biPow(a,b){for(var c=bigOne,d=a;;){if(0!=(1&b)&&(c=biMultiply(c,d)),b>>=1,0==b)break;d=biMultiply(d,d)}return c}function biPowMod(a,b,c){for(var d=bigOne,e=a,f=b;;){if(0!=(1&f.digits[0])&&(d=biMultiplyMod(d,e,c)),f=biShiftRight(f,1),0==f.digits[0]&&0==biHighIndex(f))break;e=biMultiplyMod(e,e,c)}return d}function BarrettMu(a){this.modulus=biCopy(a),this.k=biHighIndex(this.modulus)+1;var b=new BigInt;b.digits[2*this.k]=1,this.mu=biDivide(b,this.modulus),this.bkplus1=new BigInt,this.bkplus1.digits[this.k+1]=1,this.modulo=BarrettMu_modulo,this.multiplyMod=BarrettMu_multiplyMod,this.powMod=BarrettMu_powMod}function BarrettMu_modulo(a){var i,b=biDivideByRadixPower(a,this.k-1),c=biMultiply(b,this.mu),d=biDivideByRadixPower(c,this.k+1),e=biModuloByRadixPower(a,this.k+1),f=biMultiply(d,this.modulus),g=biModuloByRadixPower(f,this.k+1),h=biSubtract(e,g);for(h.isNeg&&(h=biAdd(h,this.bkplus1)),i=biCompare(h,this.modulus)>=0;i;)h=biSubtract(h,this.modulus),i=biCompare(h,this.modulus)>=0;return h}function BarrettMu_multiplyMod(a,b){var c=biMultiply(a,b);return this.modulo(c)}function BarrettMu_powMod(a,b){var d,e,c=new BigInt;for(c.digits[0]=1,d=a,e=b;;){if(0!=(1&e.digits[0])&&(c=this.multiplyMod(c,d)),e=biShiftRight(e,1),0==e.digits[0]&&0==biHighIndex(e))break;d=this.multiplyMod(d,d)}return c}var maxDigits,ZERO_ARRAY,bigZero,bigOne,dpl10,lr10,hexatrigesimalToChar,hexToChar,highBitMasks,lowBitMasks,biRadixBase=2,biRadixBits=16,bitsPerDigit=biRadixBits,biRadix=65536,biHalfRadix=biRadix>>>1,biRadixSquared=biRadix*biRadix,maxDigitVal=biRadix-1,maxInteger=9999999999999998;setMaxDigits(20),dpl10=15,lr10=biFromNumber(1e15),hexatrigesimalToChar=new Array("0","1","2","3","4","5","6","7","8","9","a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z"),hexToChar=new Array("0","1","2","3","4","5","6","7","8","9","a","b","c","d","e","f"),highBitMasks=new Array(0,32768,49152,57344,61440,63488,64512,65024,65280,65408,65472,65504,65520,65528,65532,65534,65535),lowBitMasks=new Array(0,1,3,7,15,31,63,127,255,511,1023,2047,4095,8191,16383,32767,65535); - 上面代码补充进wyy.js中之后,就可以运行生成params和encSecKey,这样每首歌曲都会生成这样一对表单数据作为参数,再由这些参数构架歌曲的地址了。如图所示。

- 显然,上面得到的结果,分别是params的值encText,以及encSecKey的值encSecKey,这也是表单数据里面的形式。经过一系列操作,把表单数据信息的加密逻辑分析明白后,再逆向读取,用Python重新模拟生成了。再看看下面的代码,是不是觉得,也不十分陌生了吧。

二、开始爬取工作
1、构建歌曲地址
- 改写get_music_url_index方法,把歌曲id和名称都加入。代码如下:
def get_data_index(self):resp = requests.post(url=self.url, data=self.data, headers=self.headers)# print(resp.text)# 此处根据web?csrf_token=链接汇总的预览栏,找到字典形式的信息,获取相应歌曲名dict_data = json.loads(resp.text)["result"]["songs"]# 而后遍历所有歌曲,获取name和idfor data in dict_data:name = data["name"]id = data["id"]# print(name, id)self.get_music_url_index(id, name)# 定义获取歌曲地址信息的方法,注意这里加入歌曲的参数iddef get_music_url_index(self, id, name):content = open("wyy.js", "r", encoding="utf-8").read()data_js = execjs.compile(content)sign = data_js.call("start", id)# 通过下面打印输出的结果,看出来表单数据的构造方法成功了# print(sign)# 应用上面构造的方法,生成表单数据data = {"params": sign["encText"],"encSecKey": sign["encSecKey"]}# 定义歌曲链接,获取源代码resp = requests.post(url=self.music_url, data=data, headers=self.headers).textmusic_url = json.loads(resp)["data"][0]["url"]print(music_url, name)
2、修改JS文件中的参数
- 上面代码写完后,相应的,wyy.js里面的start函数里面,也要加上id参数。如图。

3、成功获得歌曲链接的地址
- 效果如图。

三、保存并总结
- 由两段代码构成,首先在Music_Data类的前面写一个判断,判断根目录下有没有文件夹,没有的话就创建。
file_name = input("请手动创建保存歌曲的文件夹:") if not os.path.exists(file_name):os.mkdir(file_name) - 再到Music_Data类的里面,写一个保存的方法write_music,代码如下:
# 保存 def write_music(self, music_url, name):try:with open(f"./{file_name}/"+name+".mp3", "wb") as f:resp = requests.get(music_url).contentf.write(resp)print(name, "----保存成功")except Exception as e:print(e) - 运行一下程序,得到想要的结果。如图。

- 打开歌曲所在的文件夹,也能看到,成功。

- 总结如下:
- 以上是用js逆向的方法完成歌曲的爬取下载。用到了JavaScript技术,那么这个技术也需要熟练掌握,不然爬虫技术也是无法突破。
- 本例中,首先找到token的信息,把里面歌曲的链接地址,包括生成这个地址的加密形式的表单数据,以及歌曲的id和name都找到。然后,进一步寻找表单数据的加密逻辑,创建相应的js文件。最后,继续编写主程序代码,把构建歌曲地址的方法,以及保存歌曲的方法写入,最后成功运行。
- 当然,不用逆向,通过分析网页,预览源代码,用json方法获取字典形式的歌曲url,也是能实现爬取歌曲的目的。不过本节学习逆向方法,就绕了这么一大弯。
- 真正遇到加密性强的网站,本节练习的内容,权当是爬虫逆向的入门知识了。
- 注:想要源码的问一下anqiuxiguanli
相关文章:
js逆向爬取某音乐网站某歌手的歌曲
js逆向爬取某音乐网站某歌手的歌曲一、分析网站1、案例介绍2、寻找列表页Ajax入口(1)页面展示图。(2)寻找部分歌曲信息Ajax的token。(3)寻找歌曲链接(4)获取歌曲名称和id信息3、寻找…...
为什么软件测试面试了几个月都没有offer,从HR角度分析
首先,我觉得你在软件测试面试的过程中,逻辑比较混乱的最大一个原因是,说明你没有形成一个一个整体的体系。 导致你说的时候很多东西都杂乱无章。 我个人认为软件测试,其实开始首先进行的是一些需求的分析工作,之后呢…...
DC-7 靶场学习
文章目录信息搜集账号密码获取修改密码反弹shell得到flag信息搜集 首先获取目标ip。 arp-scan -l nmap -sP 192.168.28.0/24得到目标ip为: 192.168.28.139先访问页面。 翻译一下。 欢迎来到 DC-7DC-7引入了一些“新”概念,但我会让你弄清楚它们是什么…...
深入理解JavaScript的事件冒泡与事件捕获
前言JavaScript中提供了很多操作DOM的API。事件冒泡和事件捕获是指浏览器中处理DOM元素上事件的两种不同方式。事件冒泡和事件捕获都是JavaScript事件模型中的一部分,可以用来处理事件。对于这个问题,在实际开发中,并不是非常重要,…...
格密码学习笔记(六):格中模运算
文章目录格中取模运算CVP和格的陪集致谢格中取模运算 定义(格的基本区域) P⊂Rn:{Px∣x∈L}\mathcal{P} \subset \mathbb{R}^n : \{ \mathcal{P} \bm{x} | \bm{x} \in \mathcal{L} \}P⊂Rn:{Px∣x∈L}是Rn\mathbb{R}^nRn的一种划分。 用P\mathcal{P}P对…...
【C++】非常重要的——多态
凡是面向对象的语言,都有三大特性,继承,封装和多态,但并不是只有这三个特性,是因为者三个特性是最重要的特性,那今天我们一起来看多态! 目录 1.多态的概念 1.1虚函数 1.2虚函数的重写 1.3虚…...
发票账单很多?python助你批量完成数据提取
每天面对成堆的发票,无论是税务发票还是承兑单据,抑或是其他各类公司数据要从照片、PDF等不同格式的内容中提取,我们都有必要进行快速办公的能力提升。因此,我们的目标要求就十分明显了,首先要从图片中获取数据&#x…...
[闪存2.1] NAND FLASH特性串烧 | 不了解闪存特性,你能用好闪存产品吗?
前言 为了利用好闪存, 发挥闪存的优势, 以达到更好的性能和使用寿命, 那自然要求了解闪存特性。 闪存作为一种相对较新的存储介质, 有很多特别的特性。 一.闪存的特性 凡是采用Flash Memory的存储设备,可以统称为闪存存储。我们经常谈的固态硬盘(SSD),可以由volatile/…...
面试官问我按钮级别权限怎么控制,我说v-if,面试官说再见
最近的面试中有一个面试官问我按钮级别的权限怎么控制,我说直接v-if啊,他说不够好,我说我们项目中按钮级别的权限控制情况不多,所以v-if就够了,他说不够通用,最后他对我的评价是做过很多东西,但…...
阿里云服务器使用教程:CentOS 7安装nginx详细步骤
目录 1、下载nginx压缩包 2、配置nginx安装所需环境 3、解压nginx压缩包 4、编译安装nginx 5、nginx启动...
Android JNI浅析、Java和Native通信对象的传值和回调
简单了解一下jni JNI是一个本地编程接口,它允许运行在Java虚拟机的Java代码与用其他语言(如C,C和汇编)编写的库交互。 jni函数签名 首先看一下java类型对应的jni类型: Java类型符号BooleanZByteBCharCShortSIntILongJFloatFDo…...
linux目录/usr/lib/systemd/system目录详解
文章目录前言一. systemd介绍二. service 脚本详解2.1 [Unit] 区块2.2 [Service] 区块2.3 [Install] 区块总结前言 init的进化经历了这么几个阶段: CentOS 5: SysV init,串行 CentOS 6:Upstart,并行,借鉴ubuntu CentOS 7:Syste…...
408考研计算机之计算机组成与设计——知识点及其做题经验篇目4:CPU的功能和基本结构
随着考研的慢慢复习,我们逐渐进入了计算机组成与设计的第五章中央处理器。它原名为CPU。姓C,名PU,字中央处理器,号计组难点,乃计算机之中心与核心部件,小编称之曰能算能控,赐名曰九天宏教普济生…...
2022-12-10青少年软件编程(C语言)等级考试试卷(五级)解析
2022-12-10青少年软件编程(C语言)等级考试试卷(五级)解析T1、漫漫回国路 2020年5月,国际航班机票难求。一位在美国华盛顿的中国留学生,因为一些原因必须在本周内回到北京。现在已知各个机场之间的航班情况,求问他回不回得来(不考虑转机次数和机票价格)。 时间限制:10…...
刷题专练之链表(一)
文章目录前言一、 移除链表元素1.题目介绍2.思路3.代码二、反转链表1.题目介绍2.思路3.代码三、链表的中间结点1.题目介绍2.思路3.代码四、链表的中间结点1.题目介绍2.思路3.代码前言 以下是链表经常考的面试题,我在这里进行归纳和讲解,采取的是循序渐进…...
elasticsearch高级查询api
yml配置 #es配置 spring:elasticsearch:rest:uris: 192.168.16.188:9200添加依赖 <dependency><groupId>org.elasticsearch.client</groupId><artifactId>elasticsearch-rest-high-level-client</artifactId> </dependency>使用编程的形式…...
力扣-股票的资本损益
大家好,我是空空star,本篇带大家了解一道简单的力扣sql练习题。 文章目录前言一、题目:1393. 股票的资本损益二、解题1.正确示范①提交SQL运行结果2.正确示范②提交SQL运行结果3.正确示范③提交SQL运行结果4.正确示范④提交SQL运行结果5.其他…...
蓝桥杯刷题冲刺 | 倒计时26天
作者:指针不指南吗 专栏:蓝桥杯倒计时冲刺 🐾马上就要蓝桥杯了,最后的这几天尤为重要,不可懈怠哦🐾 文章目录1.路径2.特别数的和3.MP3储存4.求和1.路径 题目 链接: 路径 - 蓝桥云课 (lanqiao.cn…...
嵌入式软件开发之Linux 用户权限管理
目录 Ubuntu 用户系统 权限管理 权限管理命令 权限修改命令 chmod 文件归属者修改命令 chown Ubuntu 用户系统 Ubuntu 是一个多用户系统,我们可以给不同的使用者创建不同的用户账号,每个用户使用各自的账号登陆,使用用户账号的目的一是方便…...
2023-03-15 RabbitMQ
RabbitMQ整合 官网erlang版本 : 20.3.8.x 官方rabbitMq版本: rabbitmq-server-generic-unix-3.7.14.tar.xz 1.安装 1.1 安装erlang 1.安装环境 yum -y install make gcc gcc-c kernel-devel m4 ncurses-devel openssl-devel2.在/usr/local/下创建erlangapp文件…...
基于算法竞赛的c++编程(28)结构体的进阶应用
结构体的嵌套与复杂数据组织 在C中,结构体可以嵌套使用,形成更复杂的数据结构。例如,可以通过嵌套结构体描述多层级数据关系: struct Address {string city;string street;int zipCode; };struct Employee {string name;int id;…...
SciencePlots——绘制论文中的图片
文章目录 安装一、风格二、1 资源 安装 # 安装最新版 pip install githttps://github.com/garrettj403/SciencePlots.git# 安装稳定版 pip install SciencePlots一、风格 简单好用的深度学习论文绘图专用工具包–Science Plot 二、 1 资源 论文绘图神器来了:一行…...
中南大学无人机智能体的全面评估!BEDI:用于评估无人机上具身智能体的综合性基准测试
作者:Mingning Guo, Mengwei Wu, Jiarun He, Shaoxian Li, Haifeng Li, Chao Tao单位:中南大学地球科学与信息物理学院论文标题:BEDI: A Comprehensive Benchmark for Evaluating Embodied Agents on UAVs论文链接:https://arxiv.…...
学校招生小程序源码介绍
基于ThinkPHPFastAdminUniApp开发的学校招生小程序源码,专为学校招生场景量身打造,功能实用且操作便捷。 从技术架构来看,ThinkPHP提供稳定可靠的后台服务,FastAdmin加速开发流程,UniApp则保障小程序在多端有良好的兼…...
《通信之道——从微积分到 5G》读书总结
第1章 绪 论 1.1 这是一本什么样的书 通信技术,说到底就是数学。 那些最基础、最本质的部分。 1.2 什么是通信 通信 发送方 接收方 承载信息的信号 解调出其中承载的信息 信息在发送方那里被加工成信号(调制) 把信息从信号中抽取出来&am…...
Android Bitmap治理全解析:从加载优化到泄漏防控的全生命周期管理
引言 Bitmap(位图)是Android应用内存占用的“头号杀手”。一张1080P(1920x1080)的图片以ARGB_8888格式加载时,内存占用高达8MB(192010804字节)。据统计,超过60%的应用OOM崩溃与Bitm…...
Unsafe Fileupload篇补充-木马的详细教程与木马分享(中国蚁剑方式)
在之前的皮卡丘靶场第九期Unsafe Fileupload篇中我们学习了木马的原理并且学了一个简单的木马文件 本期内容是为了更好的为大家解释木马(服务器方面的)的原理,连接,以及各种木马及连接工具的分享 文件木马:https://w…...
重启Eureka集群中的节点,对已经注册的服务有什么影响
先看答案,如果正确地操作,重启Eureka集群中的节点,对已经注册的服务影响非常小,甚至可以做到无感知。 但如果操作不当,可能会引发短暂的服务发现问题。 下面我们从Eureka的核心工作原理来详细分析这个问题。 Eureka的…...
A2A JS SDK 完整教程:快速入门指南
目录 什么是 A2A JS SDK?A2A JS 安装与设置A2A JS 核心概念创建你的第一个 A2A JS 代理A2A JS 服务端开发A2A JS 客户端使用A2A JS 高级特性A2A JS 最佳实践A2A JS 故障排除 什么是 A2A JS SDK? A2A JS SDK 是一个专为 JavaScript/TypeScript 开发者设计的强大库ÿ…...
C#中的CLR属性、依赖属性与附加属性
CLR属性的主要特征 封装性: 隐藏字段的实现细节 提供对字段的受控访问 访问控制: 可单独设置get/set访问器的可见性 可创建只读或只写属性 计算属性: 可以在getter中执行计算逻辑 不需要直接对应一个字段 验证逻辑: 可以…...
