"""
Author:tanxin
Date:2021-9-25
网易云音乐根据输入,得到歌曲列表,再根据输入编号下载指定歌曲。
"""
import base64
import binascii
import json
import random
import string
from urllib import parse
import requests
from Crypto.Cipher import AES
from fake_useragent import UserAgent
def get_random():
random_str = ''.join(random.sample(string.ascii_letters + string.digits, 16))
return random_str
def len_change(text):
pad = 16 - len(text) % 16
text = text + pad * chr(pad)
text = text.encode("utf-8")
return text
def aes(text, key):
iv = b'0102030405060708'
text = len_change(text)
cipher = AES.new(key.encode(), AES.MODE_CBC, iv)
encrypted = cipher.encrypt(text)
encrypt = base64.b64encode(encrypted).decode()
return encrypt
def b(text, str):
first_data = aes(text, '0CoJUm6Qyw8W8jud')
second_data = aes(first_data, str)
return second_data
def c(text):
e = '010001'
f = '00e0b509f6259df8642dbc35662901477df22677ec152b5ff68ace615bb7b725152b3ab17a876aea8a5aa76d2e417629ec4ee341f56135fccf695280104e0312ecbda92557c93870114af6c9d05c4f7f0c3685b7a46bee255932575cce10b424d813cfe4875d3e82047b97ddef52741d546b8e289dc6935b3ece0462db0a22b8e7'
text = text[::-1]
result = pow(int(binascii.hexlify(text.encode()), 16), int(e, 16), int(f, 16))
return format(result, 'x').zfill(131)
def get_final_param(text, str):
params = b(text, str)
encSecKey = c(str)
return {'params': params, 'encSecKey': encSecKey}
def get_music_list(params, encSecKey):
url = "https://music.163.com/weapi/cloudsearch/get/web?csrf_token="
payload = 'params=' + parse.quote(params) + '&encSecKey=' + parse.quote(encSecKey)
headers = {
'authority': 'music.163.com',
'user-agent': UserAgent().random,
'content-type': 'application/x-www-form-urlencoded',
'accept': '*/*',
'origin': 'https://music.163.com',
'sec-fetch-site': 'same-origin',
'sec-fetch-mode': 'cors',
'sec-fetch-dest': 'empty',
'referer': 'https://music.163.com/search/',
'accept-language': 'zh-CN,zh;q=0.9',
}
response = requests.request("POST", url, headers=headers, data=payload)
return response.text
def get_reply(params, encSecKey):
url = "https://music.163.com/weapi/song/enhance/player/url/v1?csrf_token="
payload = 'params=' + parse.quote(params) + '&encSecKey=' + parse.quote(encSecKey)
headers = {
'authority': 'music.163.com',
'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.135 Safari/537.36',
'content-type': 'application/x-www-form-urlencoded',
'accept': '*/*',
'origin': 'https://music.163.com',
'sec-fetch-site': 'same-origin',
'sec-fetch-mode': 'cors',
'sec-fetch-dest': 'empty',
'referer': 'https://music.163.com/',
'accept-language': 'zh-CN,zh;q=0.9'
}
response = requests.request("POST", url, headers=headers, data=payload)
return response.text
def res():
url_list=[]
name_list=[]
song_name = input('请输入歌曲名称,按回车键搜索:')
d = {"hlpretag": "<span class=\"s-fc7\">", "hlposttag": "</span>", "s": song_name, "type": "1", "offset": "0",
"total": "true", "limit": "30", "csrf_token": ""}
d = json.dumps(d)
random_param = get_random()
param = get_final_param(d, random_param)
song_list = get_music_list(param['params'], param['encSecKey'])
print('搜索结果如下:')
if len(song_list) > 0:
song_list = json.loads(song_list)['result']['songs']
for i, item in enumerate(song_list):
item = json.dumps(item)
print(str(i+1) + ":" + json.loads(str(item))['name'])
d = {"ids": "[" + str(json.loads(str(item))['id']) + "]", "level": "standard", "encodeType": "",
"csrf_token": ""}
d = json.dumps(d)
param = get_final_param(d, random_param)
song_info = get_reply(param['params'], param['encSecKey'])
if len(song_info) > 0:
song_info = json.loads(song_info)
song_url = json.dumps(song_info['data'][0]['url'], ensure_ascii=False)
print(song_url)
url_list.append(song_url)
name_list.append(json.loads(str(item))['name'])
else:
print("该首歌曲解析失败,可能是因为歌曲格式问题")
"""
歌曲下载界面
"""
while True:
print('下载选择:1-20,ALL全部,Q返回查找,Z退出程序,显示为null的表示没有版权或vip才能下载')
song_id = input('请输入下载编号:')
if song_id=='ALL':
for j in range(len(url_list)):
url = url_list[j].replace('"', '')
name = name_list[j] + url.split('/')[-1].split('.')[0]
try:
mp3 = requests.get(url=url, headers={'User-Agent': UserAgent().random}).content
with open(f'./{name}.mp3', 'wb') as f:
f.write(mp3)
print(name, "下载完成!")
except:
print(name,'这首歌无法下载!')
continue
else:
print('这首歌已下载!')
break
if song_id=='Q':
res()
break
if song_id=='Z':
print('退出下载!')
break
if int(song_id)>=1 and int(song_id)<=20:
url=url_list[int(song_id) - 1].replace('"','')
name=name_list[int(song_id)-1]+url.split('/')[-1].split('.')[0]
try:
mp3 = requests.get(url=url,headers={'User-Agent':UserAgent().random}).content
except:
print(name,'这首歌无法下载!')
continue
with open(f'./{name}.mp3','wb') as f:
f.write(mp3)
print(name,"下载完成!")
else:
print('请根据提示输入!本次程序')
res()
break
else:
print("很抱歉,未能搜索到相关歌曲信息")
if __name__ == '__main__':
res()
代码参考:https://blog.csdn.net/zgbzbl/article/details/107773755?utm_medium=distribute.pc_relevant.none-task-blog-2~default~baidujs_utm_term~default-0.no_search_link&spm=1001.2101.3001.4242