【这就是标题】
距离上一次发推送差不多有一个月了ヽ(ー_ー)ノ
做了一个小的酷狗音乐下载器,公众号内回复704就可以收到下载链接。
长下面这样。
双击打开,会提示让输入你要搜索的歌曲。
这里输入去流浪然后回车或者鼠标点击ok,会让选择下载几首,因为音乐网站搜索歌曲会根据你的关键词出来非常多首歌,因为懒,这里就限制了第一页(一般来说前面几首大概就是你想要下载的歌曲了),酷狗一页是30首,所以最大填30。
反正超过了30代码也只按30处理(ノ ̄▽ ̄)
回车,然后。
删帧删花了  ̄へ ̄
速度取决于网速,歌曲会下载到你打开下载器时的路径。
【把公众号的内容搬了个家】
因为更新推送时间不稳定又没有推文章,而公众号的机制和B站视频的推送机制是不一样的,所以就用码云托管了一个花里胡哨的网页用来放置公众号内容。
欢迎访问:http://space-earth.gitee.io,基本上是在之前这篇内容上做了一些调整。
Starry Sky:来做个自己的网页吧!(一)zhuanlan.zhihu.com【下面是记录音乐下载器的生产过程】
代码的基本设计思路通过搜索歌曲然后下载对应内容。
进入到酷狗网站首页随便搜索一首歌,这里仍然以去流浪为例,得到30首歌曲,如下。
更多内容请下载客户端
此页面地址长下面这样。
一看就是老规律家了,so easy。
再点击第一首歌进入播放页,会打开一个新页面。
观察此页面地址。
很容易看出来结构是.../song/+对应的hash值以及所谓的album_id,但是不是都是这样呢,经过一番验证,发现播放的歌曲地址都是这个结构。
简单了,哈希算法我虽然不熟,但我知道这个哈希值服务器是肯定要发送到客户端没跑的。
回到歌曲的搜索页面,打开开发者工具,一顿基操,发现了下面已经蓝色选中的这个脚本。
打开预览信息一看,嚯,这数据格式我熟。
很容易地在lists当中找到了所有的歌曲信息,其中就包含了歌曲播放页面的hash值和专辑id,大功即将告成。
观察下这个脚本请求的地址。
挤在一堆不方便梳理,往下滑看到了查询时所有应该带上的字符串参数。
所有的参数只有红框的部分在发生改变,第一个红框刷新几次观察结合参数名,基本是时间戳没跑了,保险起见在控制台输出一下当前时间戳发现确实是时间戳。
离成功又近了一步,才怪<( ̄ ﹌  ̄)> !
signnature,这单词我认识,签名嘛,去找一下哪里返回来的就行。
Two thousand years later...
有时候放弃也不失为一个明智的选择,没找到这玩意哪里来的。
那可咋行啊,没有这玩意就没办法组成地址,没有地址就拿不到歌曲的hash值和专辑id,没有hash值和专辑id就没法请求播放页面,没有播放需求服务器怎么会把歌曲发送给客户端,服务器不发送歌曲给客服端怎么拿到歌曲在服务器上的地址,没有歌曲地址怎么下载歌曲......
果然,有时候放弃是明智的。
callback怎么看着就那么与众不同呢,嚯,回调函数哦!我也不在这找了,换个思路去歌曲播放页面找找,很容易的在网页信息中找到了播放地址。
但是这个播放地址看起来是不像是好惹的,一眼看不出有啥规律,刷新一下发现紧随.com/后的是当前的时间(年月日时分),嗯,很不错。
懒得管你怎么搞的,花里胡哨的一律默认服务器都会发给我。
找到了,打开看一下。
地址搞定了,复制打开一看没毛病。
去流浪周笔畅 - 去流浪
好,右键音频另存为保存到本地就可以了。
等,等等...是不是还忘了啥......好像是要用Python下载....
观察一下这个请求的访问地址。
也是带了一堆参数。
这熟悉的callback,你怎么长这么大了,怎么和上一页那个干干净净的callback123不太搭了,不过这都不重要。
下面第一张图片是搜索页歌曲信息对应请求地址,第二张图是播放页面歌曲信息对应请求地址。
虽然有很多相似,但是仍然看不出来什么,难道只有去研究它的脚本文件看看回调函数到底做了哪些事情嘛?
算了算了,我记得w3c是个好东西,找了下远古时代的一篇下载器,提供了两个接口,其中一个和播放页歌曲信息请求地址很相似,另一个不曾见过,但两者都十分简单,长这样。
看起来像是这些年酷狗在这个接口的基础上继续盖了东西,最后一顿操作,在第一个简单的接口上加上现在搜索页歌曲信息的这一堆callback后的参数,把privilege_filter以后的参数全部砍掉换成播放页面歌曲信息接口的最后一个查询参数,终于得到了所有歌曲信息的内容。
这个接口只需要更改关键词即可组成该关键词搜索页面的地址,到了这一步,代码就很容易了。
贴一下。
import requests
from bs4 import BeautifulSoup
import json,sys
import easygui as g
while True:
search = g.enterbox('请输入你想搜索的歌曲:',title='酷狗音乐下载器')
if search ==None:
sys.exit()
if search!='':
break
while True:
number = g.enterbox('请输入你想下载多少首搜索出的歌曲,请输入对应数字(最多30):', title='酷狗音乐下载器')
if number ==None:
sys.exit()
if number != '':
break
if int(number)>30:
number='30'
search_headers={
'referer':'https: // www.kugou.com/song /',
'user-agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.89 Safari/537.36'
}
search_results = 'http://songsearch.kugou.com/song_search_v2?callback=jQuery19109017207142454389_1595994946923&keyword='+search +
'&page=1&pagesize=30&userid=-1&clientver=&platform=WebFilter&tag=em&filter=2&iscorrection=1&privilege_filter=0&_=1595994946925%27'
res=requests.get(search_results,headers=search_headers)
song_json =json.loads(res.text[res.text.index('(') + 1:-2])
song_list=song_json['data']['lists']
a=0
final_number=int(number)
for i in song_list:
if a==int(number):
break
song_hash = i['FileHash']
song_id = i['AlbumID']
song_name = i['FileName'].replace('<em>','').replace('</em>','')
song_url = 'https://wwwapi.kugou.com/yy/index.php?r=play/getdata&callback=jQuery19109017207142454389_1595994946923&hash='+song_hash+'&album_id='+song_id+'&dfid=1aF52t2JD7yx11ML0H2JZ9UE&mid=2391153464a766aea6860623fc508772&platid=4&_=1595994946925'
song_res = requests.get(song_url, headers=search_headers)
song_js = json.loads(song_res.text[song_res.text.index('(') + 1:-2])
url = song_js['data']['play_url']
if url!='':
res_finnal = requests.get(url, headers=search_headers)
with open(song_name+'.mp3', 'wb') as f:
f.write(res_finnal.content)
print('【'+song_name+'.mp3】下载完成')
else:
print('【'+song_name+'.mp3】无版权,无法下载!')
final_number-=1
a += 1
print('-----------------------------------')
print('【'+str(final_number)+'首音乐已下载完毕!】')
最后使用pyinstaller打包一下,就得到了本文开头的酷狗音乐下载器。