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 requests
class 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和id for 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和id for data in dict_data: name = data["name"] id = data["id"] # print(name, id) self.get_music_url_index(id, name) # 定义获取歌曲地址信息的方法,注意这里加入歌曲的参数id def 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).text music_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).content f.write(resp) print(name, "----保存成功") except Exception as e: print(e)
- 运行一下程序,得到想要的结果。如图。
- 打开歌曲所在的文件夹,也能看到,成功。
- 总结如下:
- 以上是用js逆向的方法完成歌曲的爬取下载。用到了JavaScript技术,那么这个技术也需要熟练掌握,不然爬虫技术也是无法突破。
- 本例中,首先找到token的信息,把里面歌曲的链接地址,包括生成这个地址的加密形式的表单数据,以及歌曲的id和name都找到。然后,进一步寻找表单数据的加密逻辑,创建相应的js文件。最后,继续编写主程序代码,把构建歌曲地址的方法,以及保存歌曲的方法写入,最后成功运行。
- 当然,不用逆向,通过分析网页,预览源代码,用json方法获取字典形式的歌曲url,也是能实现爬取歌曲的目的。不过本节学习逆向方法,就绕了这么一大弯。
- 真正遇到加密性强的网站,本节练习的内容,权当是爬虫逆向的入门知识了。
- 注:想要源码的问一下anqiuxiguanli