Python爬取酷狗MP3音频的步骤
分析问题
音频url
点入某个音乐的播放界面,通过F12-Network,分析数据,可以看到有一个index.php?..返回数据中有一个play_url,打开后正是我们需要的音频。
查看该url的headers,其params参数如下,通过反复不同的几次尝试,得知r、callback、dfid、mid、platid这几项不变,而通过初步的requests尝试,发现最后一项'_'可有可无,改变的只有hash和album_id两项。
r:play/getdata callback:jQuery1910861615852090795_1612578519454 hash:EF0DA656831F08B1FD2CB855BC38ED2C dfid:0Q0Clh1IcZaG3ey1J70RaTiL mid:b6cf66837b18642cc269390b066649dc platid:4 album_id:41669581 _:1612578519455
搜索url
得知改变的只有两项后,那就容易多了,在搜索歌曲界面Network,发现song?...该url返回值中有hash和album_id存在,我们之后只用搜索结果第一项(一般要搜的歌曲排名第一)。
同样分析其params参数,改变的只有keyword、signature、clienttime、mid、uuid。后三者可以比较容易看出其为毫秒级时间戳(13位),keyword也挺容易明白,signature哪里找呢?通过全局搜索signature,发现有一个js文件中含有该关键词。
callback:callback123 keyword:花海 page:1 pagesize:30 bitrate:0 isfuzzy:0 tag:em inputtype:0 platform:WebFilter userid:-1 clientver:2000 iscorrection:1 privilege_filter:0 srcappid:2919 clienttime:1612579100435 mid:1612579100435 uuid:1612579100435 dfid:- signature:472F60133C23184CAFC5005350C90229
JS
找到的js代码如下
"undefined"==typeoffaultylabs&&(faultylabs={}),
faultylabs.MD5=function(a){
functionb(a){
varb=(a>>>0).toString(16);
return"00000000".substr(0,8-b.length)+b
}
functionc(a){
for(varb=[],c=0;cc;c++)
b.push(255&a),
a>>>=8;
returnb
}
functione(a,b){
returna<>>32-b
}
functionf(a,b,c){
returna&b|~a&c
}
functiong(a,b,c){
returnc&a|~c&b
}
functionh(a,b,c){
returna^b^c
}
functioni(a,b,c){
returnb^(a|~c)
}
functionj(a,b){
returna[b+3]<<24|a[b+2]<<16|a[b+1]<<8|a[b]
}
functionk(a){
for(varb=[],c=0;c=0;e--)
d=arguments[e],
c=255&d,
d>>>=8,
c<<=8,
c|=255&d,
d>>>=8,
c<<=8,
c|=255&d,
d>>>=8,
c<<=8,
c|=d,
a+=b(c);
returna
}
functionm(a){
for(varb=newArray(a.length),c=0;c56){
for(vark=0;64-c>k;k++)
p.push(0);
c=p.length%64
}
for(k=0;56-c>k;k++)
p.push(0);
p=p.concat(d(8*b));
varm=1732584193
,o=4023233417
,q=2562383102
,r=271733878
,s=0
,t=0
,u=0
,v=0;
for(k=0;k
在274行发现h.signature=faultylabs.MD5(o.join("")),初步理解为signature是o内部元素拼接成字符串,对其加上断点并将o加入watch。
0:"NVPh5oo715z5DIWAeQlhMDsWXXQV4hwt"
1:"bitrate=0"
2:"callback=callback123"
3:"clienttime=1612580098162"
4:"clientver=2000"
5:"dfid=-"
6:"inputtype=0"
7:"iscorrection=1"
8:"isfuzzy=0"
9:"keyword=花海"
10:"mid=1612580098162"
11:"page=1"
12:"pagesize=30"
13:"platform=WebFilter"
14:"privilege_filter=0"
15:"srcappid=2919"
16:"tag=em"
17:"userid=-1"
18:"uuid=1612580098162"
19:"NVPh5oo715z5DIWAeQlhMDsWXXQV4hwt"
length:20
在watch里不难发现o为一个长度为20的数组,之后我们按之前理解将字符串拼接。
NVPh5oo715z5DIWAeQlhMDsWXXQV4hwtbitrate=0callback=callback123clienttime=1612580098162clientver=2000dfid=-inputtype=0iscorrection=1isfuzzy=0keyword=花海mid=1612580098162page=1pagesize=30platform=WebFilterprivilege_filter=0srcappid=2919tag=emuserid=-1uuid=1612580098162NVPh5oo715z5DIWAeQlhMDsWXXQV4hwt
之后要js解密,这谁会?反正我不会0.0,那也有办法,用python调用js文件。在274行分析为md5加密,往前找看看有没有相关函数,果真有一个,将其保存为kugou.js
"undefined"==typeoffaultylabs&&(faultylabs={}),
faultylabs.MD5=function(a){
functionb(a){
varb=(a>>>0).toString(16);
return"00000000".substr(0,8-b.length)+b
}
functionc(a){
for(varb=[],c=0;cc;c++)
b.push(255&a),
a>>>=8;
returnb
}
functione(a,b){
returna<>>32-b
}
functionf(a,b,c){
returna&b|~a&c
}
functiong(a,b,c){
returnc&a|~c&b
}
functionh(a,b,c){
returna^b^c
}
functioni(a,b,c){
returnb^(a|~c)
}
functionj(a,b){
returna[b+3]<<24|a[b+2]<<16|a[b+1]<<8|a[b]
}
functionk(a){
for(varb=[],c=0;c=0;e--)
d=arguments[e],
c=255&d,
d>>>=8,
c<<=8,
c|=255&d,
d>>>=8,
c<<=8,
c|=255&d,
d>>>=8,
c<<=8,
c|=d,
a+=b(c);
returna
}
functionm(a){
for(varb=newArray(a.length),c=0;c56){
for(vark=0;64-c>k;k++)
p.push(0);
c=p.length%64
}
for(k=0;56-c>k;k++)
p.push(0);
p=p.concat(d(8*b));
varm=1732584193
,o=4023233417
,q=2562383102
,r=271733878
,s=0
,t=0
,u=0
,v=0;
for(k=0;k
之后用python的pyexecjs库调用,但是注意调用的时候的名字是execjs。
代码实现
"""
data:2021/02/05
通过搜索爬取酷狗音乐,付费音乐暂时只能爬取试听部分。
"""
importrequests
importre
importjson
importtime
importexecjs
defget_signature(text):
"""
获取signature值
:paramtext:格式化之后的字符串
:return:返回酷狗网站上加密后的signature
"""
#读取js文件内容
withopen("kugou.js","r",encoding='utf-8')asf:
js_str=f.read()
#通过js文件中逻辑数据,对文件进行加密
ifjs_str:
js_obj=execjs.compile(js_str)
returnjs_obj.call('faultylabs.MD5',text)
defget_url(keyword):
"""
获取搜索之后的url
:paramkeyword:搜索词,如晴天
:return:返回完整的url地址
"""
search="https://complexsearch.kugou.com/v2/search/song?callback=callback123&keyword={keyword}&page=1&pagesize=30&bitrate=0&isfuzzy=0&tag=em&inputtype=0&platform=WebFilter&userid=-1&clientver=2000&iscorrection=1&privilege_filter=0&srcappid=2919&clienttime={time}&mid={time}&uuid={time}&dfid=-&signature={signature}"
key_code="NVPh5oo715z5DIWAeQlhMDsWXXQV4hwtbitrate=0callback=callback123clienttime={time}clientver=2000dfid=-inputtype=0iscorrection=1isfuzzy=0keyword={keyword}mid={time}page=1pagesize=30platform=WebFilterprivilege_filter=0srcappid=2919tag=emuserid=-1uuid={time}NVPh5oo715z5DIWAeQlhMDsWXXQV4hwt"
#获得13位时间戳
millis=str(round(time.time()*1000))
p=key_code.format(time=millis,keyword=keyword)
signature=get_signature(p)
#print(signature)
search_url=search.format(keyword=keyword,time=millis,signature=signature)
returnsearch_url
defget_data(url):
headers={
'user-agent':'Mozilla/5.0(WindowsNT10.0;Win64;x64)AppleWebKit/537.36(KHTML,likeGecko)Chrome/88.0.4324.146Safari/537.36',
'referer':'https://www.kugou.com/',
'authority':'complexsearch.kugou.com',
}
res=requests.get(url=url,headers=headers)
#将获取的数据转为json格式
data=re.findall('callback123\((.*)\)',res.text,re.S)[0]
json_data=json.loads(data)['data']
hash_value=json_data['lists'][0]['FileHash'].lower()
album_id=json_data['lists'][0]['AlbumID']
returnhash_value,album_id
defget_mp3(hash_value,album_id):
"""
获取MP3音频文件
:paramhash_value:传入哈希值
:paramalbum_id:传入albumid
:return:none
"""
url='https://wwwapi.kugou.com/yy/index.php'
params={
'r':'play/getdata',
'callback':'jQuery191019800824574510756_1612519333214',
'hash':str(hash_value),
'dfid':'0Q0Clh1IcZaG3ey1J70RaTiL',
'mid':'b6cf66837b18642cc269390b066649dc',
'platid':'4',
'album_id':str(album_id),
}
headers={
'user-agent':'Mozilla/5.0(WindowsNT10.0;Win64;x64)AppleWebKit/537.36(KHTML,likeGecko)Chrome/88.0.4324.146Safari/537.36',
'referer':'https://www.kugou.com/',
'authority':'wwwapi.kugou.com',
}
res=requests.post(url=url,params=params,headers=headers)
data=re.findall('jQuery191019800824574510756_1612519333214\((.*?)\);',res.text,re.S)[0]
json_data=json.loads(data)
audio_name=json_data['data']['audio_name']
play_url=json_data['data']['play_url']
save_mp3(audio_name,play_url)
defsave_mp3(audio_name,play_url):
"""
保持MP3文件
:paramaudio_name:传入命名
:paramplay_url:传入音频url
:return:none
"""
content=requests.get(play_url).content
withopen(audio_name+'.mp3',mode='ab')asf:
f.write(content)
if__name__=='__main__':
try:
keyword=input('请输入要搜索的歌曲名称:')
hash_value,album_id=get_data(get_url(keyword))
get_mp3(hash_value,album_id)
exceptExceptionase:
print('请输入正确歌曲名称。')
以上就是Python爬取酷狗MP3音频的步骤的详细内容,更多关于Python爬取酷狗MP3音频的资料请关注毛票票其它相关文章!
声明:本文内容来源于网络,版权归原作者所有,内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎发送邮件至:czq8825#qq.com(发邮件时,请将#更换为@)进行举报,并提供相关证据,一经查实,本站将立刻删除涉嫌侵权内容。