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;c 56){ 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;c 56){ 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(发邮件时,请将#更换为@)进行举报,并提供相关证据,一经查实,本站将立刻删除涉嫌侵权内容。