爬取酷我音乐相比网易云音乐、酷狗音乐以及QQ音乐来说容易很多,没有加密算法,而且在反爬虫中不存在一些难理解的逻辑,只需要理清思路即可!本文会用爬虫 GUI制作酷我音乐下载工具
GUI编写思路
本文的爬虫程序是根据下面的GUI界面进行封装的,GUI创建是使用PySimpleGUI
库:
所以GUI制作思路是这样的:
- 通过搜索框搜索歌曲名称或者歌手,取得歌曲的名称等信息,通过信息展示框进行展示以及传入歌曲选择框中。
- 在歌曲选择框中输入歌曲信息或者选择要保存的歌曲,然后点击Button按钮保存。
- 点击保存按钮会出现一个弹框,可以选择音频数据保存的路径。
- Button按钮退出程序直接结束工具的运行。
根据设计图以及思路得到下面代码:
代码语言:javascript复制# 主题设置
sg.theme('BrownBlue') # BrownBlue LightBrown3
# 布局设置 类似网页前端代码
layout = [ # 搜索框布局 Text:文本 Combo:输入框 tooltip:鼠标移动到输入框显示的内容 size:输入框宽度 Button:按钮 key:唯一标识
[sg.Text('请输入搜索的歌曲或歌手:', font=("微软雅黑", 12)),
sg.Combo(values='', tooltip='请输入搜索的歌曲或歌手:', font=("微软雅黑", 10), default_value='', auto_size_text=True,
size=(70, 0), key='keys'), sg.Button('搜索', font=("微软雅黑", 12))],
# 歌曲选择框布局
[sg.Text('请选择或输入要保存的歌:', font=("微软雅黑", 12)),
sg.Combo(values='', tooltip='请选择或输入要保存的歌:', font=("微软雅黑", 10), default_value='', auto_size_text=True,
size=(70, 0), key='value'), sg.Button('保存', font=("微软雅黑", 12))],
# 信息展示框 Output:输出元素
[sg.Text('信息展示:', justification='center')],
[sg.Output(size=(100, 10), font=("微软雅黑", 10))],
# 退出程序按钮
[sg.Text('', font=("微软雅黑", 12), size=(73, 1)),sg.Button('退出程序', font=("微软雅黑", 12))]
]
# 创建窗口
window = sg.Window('酷我音乐下载器', layout, font=("微软雅黑", 12), default_element_size=(80, 1))
# 事件循环 类似网页后端代码
while True:
event, values = window.read()
# 点击退出程序按时结束事件循环
if event in (None, '退出程序'):
break
window.close()
GUI布局完成,后面只需要编写爬虫以及在事件循环中增加相关后端代码即可!
爬虫编写思路
根据GUI结构,我们需要一个搜索功能,这里直接在酷我音乐首页搜索框搜索音乐抓包,拿到搜索框搜索内容的ap:i
得到url:
代码语言:javascript复制http://www.kuwo.cn/api/www/search/searchMusicBykeyWord?key=毛不易&pn=1&rn=30&httpsStatus=1&reqId=705d4d00-cd07-11eb-bb69-59cd8661b1da
其中key
是搜索的内容,pn
是页码,rn
是数据的条数,reqId
没看出来,但不要紧,不影响操作。url的参数基本了解了,其中修改key
值即可获取不同歌曲数据,最终得到data_text()
函数。
def data_text(key):
global headers # 后面需要用到,设置为全局变量
keys = urllib.parse.quote(key) # 把得到的key转化为电脑看得懂的符号
headers = {
'Cookie': '你的cookie',
'csrf': 'GVDHKPAN1HS',
'Host': 'www.kuwo.cn',
'Referer': f'http://www.kuwo.cn/search/list?key={keys}',
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.104 Safari/537.36'
}
url_rid = f'http://www.kuwo.cn/api/www/search/searchMusicBykeyWord?key={keys}&pn=1&rn=30&httpsStatus=1&reqId=8468f010-a011-11eb-9364-1b542cb8c9e7Request Method'
return url_rid
虽然得到了该url,但我们还不知要从url中提取哪些内容;所以我们需要进入下一页面,继续抓包,找到上一条url和下一条url的关联性。
随便点击任意一首歌曲,当然,付费歌曲是无法在网页上播放的,但酷我音乐的付费内容和免费内容都是用一条链接的,所以播放免费歌曲进入播放页:
在播放页抓包,成功找到包含MP3格式的数据包,得到url:
代码语言:javascript复制http://www.kuwo.cn/url?format=mp3&rid=28501751&response=url&type=convert_url3&br=128kmp3&from=web&t=1623690057540&httpsStatus=1&reqId=168e5e60-cd32-11eb-ba7a-a1bfcaa82f84
经过测试,只需要url中的参数rid
发生变化即可获取不同的歌曲,最后获得MP3url_rid()
和MP3_URL()
函数:
def MP3url_rid(url_rid):
data = []
rid_response = requests.get(url_rid, headers=headers).json()
lists = rid_response['data']['list']
for i in lists:
time.sleep(2)
name = i['name'] # 歌名
artist = i['artist'] # 歌手
rid = i['rid'] # id值
data.append([name, artist, rid])
print(name, artist, rid, sep=' | ')
# 传入到歌曲选择框选择
window["value"].Update(values=data, font=("微软雅黑", 10), size=(15, 8))
def MP3_URL(file_s, name, artist, rid):
url_mp3 = f'http://www.kuwo.cn/url?format=mp3&rid={rid}&response=url&type=convert_url3&br=128kmp3&from=web&t=1618728266452&httpsStatus=1&reqId=849a8760-a011-11eb-9364-1b542cb8c9e7'
url_response = requests.get(url=url_mp3, headers=headers).json()
mp3_url = url_response['url']
mp3_name = name '_' artist '.mp3'
print(mp3_name)
# 传入保存函数进行保存
save(file_s, mp3_name, mp3_url)
条件循环
在事件循环中加入点击搜索按钮和保存按钮所触发的事件:
代码语言:javascript复制if event == '搜索':
if values['keys']:
# 接收搜索框内容
key = values['keys']
# 传入函数
url_rid = data_text(key)
MP3url_rid(url_rid)
print('搜索完成, 请选择要下载的歌曲!')
# 弹窗
sg.popup('搜索完成, 请选择要下载的歌曲!')
else:
print('歌曲或歌手未输入!')
sg.popup('歌曲或歌手未输入!')
if event == '保存':
if values['value']:
# sg.popup_get_folder() 弹窗的一种,接收的是文件路径
files = sg.popup_get_folder('请选择存储路径:')
# 接收MP3url_rid()函数内容
mp3data = values['value']
q = mp3data[0]
w = mp3data[1]
e = mp3data[2]
MP3_URL(files, q, w, e)
print('下载完成!')
sg.popup('下载完成!')
else:
print('未选择或者输入歌曲!')
sg.popup('未选择或者输入歌曲!')
运行示例,最后可以用pyinstaller进行程序代码打包: