今天用Python来实现一下酷狗JS逆向,实现搜索下载功能
1、环境使用
- Python 3.8
- Pycharm
2、模块使用
import hashlib --> pip install hashlib
import prettytable as pt --> pip install prettytable
import requests --> pip install requests
import time
import re
import json
3、实现思路
数据来源分析
1. 明确需求
- 明确采集网站以及数据内容:
网址: ku狗音乐网站
数据: 音频链接 / 音频名称
2. 抓包分析
- 通过开发者工具进行抓包分析
I. 打开开发者工具: F12 / 右键点击检查选择network <网络>
II. 刷新网页: 让数据内容重新加载一遍
III. 找音频链接地址: 点击媒体 <media>
音频链接:
IV. 分析音频链接地址, 是从哪里来的: 通过关键字搜索找到对应数据包位置
<数据包接口, 存储音频相关数据信息>
代码实现步骤
1. 发送请求, 模拟浏览器对于url地址发送请求
url地址: 分析得到数据包链接
2. 获取数据, 获取服务器返回响应数据
开发者工具: response <响应>
3. 解析数据, 提取我们需要的数据内容
数据: 音频链接 / 歌名
4. 保存数据, 保存音频内容
对于音频链接发送请求, 获取二进制数据内容 <音频内容>
4、源码展示
接来下看看源码
# 导入数据请求模块
import requests
# 导入正则表达式模块
import re
# 导入json
import json
# 导入制表模块
import prettytable as pt
import hashlib
import time
def md5_hash(date, word):
text = [
'NVPh5oo715z5DIWAeQlhMDsWXXQV4hwt',
'appid=1014',
'bitrate=0',
'callback=callback123',
f'clienttime={date}',
'clientver=1000',
'dfid=2UHYNz3g5BlC1P5mfH2586l5',
'filter=10',
'inputtype=0',
'iscorrection=1',
'isfuzzy=0',
f'keyword={word}',
'mid=6cff5eec372eb97a1152cedd1d7c9fd5',
'page=1',
'pagesize=30',
'platform=WebFilter',
'privilege_filter=0',
'srcappid=2919',
'token=84444db71f298ea679c54e933acfdbe5065b7e0dd17b6bd7c2384cccde1f45c0',
'userid=458167322',
'uuid=6cff5eec372eb97a1152cedd1d7c9fd5',
'NVPh5oo715z5DIWAeQlhMDsWXXQV4hwt'
]
string = ''.join(text)
md5 = hashlib.md5()
md5.update(string.encode('utf-8'))
signature = md5.hexdigest()
print(signature)
return signature
date = int(time.time() * 1000)
key_word = input('请输入你要下载的歌曲/歌手:')
signature = md5_hash(date=date, word=key_word)
# 1. 发送请求
link = 'https://complexsearch.***.com/v2/search/song'
# 模拟浏览器: headers 请求头 字典数据类型, 构建完整键值对
headers = {
'Referer': 'https://www.***.com/',
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/116.0.0.0 Safari/537.36',
}
# 请求参数
link_data = {
'callback': 'callback123',
'srcappid': '2919',
'clientver': '1000',
'clienttime': date,
'mid': '6cff5eec372eb97a1152cedd1d7c9fd5',
'uuid': '6cff5eec372eb97a1152cedd1d7c9fd5',
'dfid': '2UHYNz3g5BlC1P5mfH2586l5',
'keyword': key_word,
'page': '1',
'pagesize': '30',
'bitrate': '0',
'isfuzzy': '0',
'inputtype': '0',
'platform': 'WebFilter',
'userid': '458167322',
'iscorrection': '1',
'privilege_filter': '0',
'filter': '10',
'token': '84444db71f298ea679c54e933acfdbe5065b7e0dd17b6bd7c2384cccde1f45c0',
'appid': '1014',
'signature': signature,
}
# 发送请求
response = requests.get(url=link, params=link_data, headers=headers)
"""
2. 获取数据
3. 解析数据
"""
html_data = re.findall('callback123\((.*)', response.text)[0].replace(')', '')
# 把json字符串, 转成字典数据
json_data = json.loads(html_data)
tb = pt.PrettyTable()
tb.field_names = ['序号', '歌名', '歌手', '专辑', 'ID']
lis = []
num = 1
# for循环遍历
for index in json_data['data']['lists']:
dit = {
'歌名': index['SongName'],
'歌手': index['SingerName'],
'专辑': index['AlbumName'],
'ID': index['EMixSongID'],
}
lis.append(dit)
tb.add_row([str(num), index['SongName'], index['SingerName'], index['AlbumName'], index['EMixSongID']])
num += 1
print(tb)
def save(music_id):
# 请求链接, 数据包链接地址
url = 'https://wwwapi.***.com/yy/index.php'
# 请求参数 -> 使用data字典接收请求参数
data = {
'r': 'play/getdata',
# 'callback': 'jQuery1910438191389285846_1693915941407',
'dfid': '2UHYNz3g5BlC1P5mfH2586l5',
'appid': '1014',
'mid': '6cff5eec372eb97a1152cedd1d7c9fd5',
'platid': '4',
'encode_album_audio_id': music_id,
'_': '1693915941408',
}
# 发送请求 -> 返回响应对象 <Response [200]>
response = requests.get(url=url, params=data, headers=headers)
# 歌名
audio_name = response.json()['data']['audio_name']
# 音频链接
play_url = response.json()['data']['play_url']
# 对于音频链接发送请求, 获取二进制数据
music_content = requests.get(url=play_url, headers=headers).content
# 保存到本地文件夹 \ 转义字符串
with open('music\\' + audio_name + '.mp3', mode='wb') as f:
# 写入内容
f.write(music_content)
print(play_url, audio_name)
page = input('请输入你想要下载歌曲序号 / 全部下载<0>: ')
try:
if page == '0':
for li in lis:
save(music_id=li['ID'])
else:
save(music_id=lis[int(page)-1]['ID'])
except Exception as e:
print('你可能输入有误', e)
5、效果展示
最后就全部爬取到手了
担心大家看不懂代码,我特意录制了视频详细讲解,跟代码一起打包好了,文章最后的名片自取即可~
6、最后
好了,分享就到这结束,下次见!