Python JS逆向之酷狗,实现搜索下载功能

今天用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
# 担心大家看不懂代码,我特意录制了视频详细讲解
# 跟代码一起打包好放在这个抠裙了 592539176 ~
 
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.kugou.com/v2/search/song'
# 模拟浏览器: headers 请求头 字典数据类型, 构建完整键值对
headers = {
    'Referer': 'https://www.kugou.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.kugou.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、最后

好了,分享就到这结束,下次见!

 

 

posted @ 2023-10-17 15:35  轻松学Python  阅读(182)  评论(1编辑  收藏  举报