[Python] 网*云音乐下载python版 |
|
Walker
管理员
L12
• 2018-09-10 • 回复 7 • 只看楼主
• 举报
|
代码篇幅有点长,废话不说,直接上代码
#!python3
# -*- coding: utf-8 -*-
"""
@author: Heanny
@contact: [email]lzh@heanny.cn[/email]
@site:
@software: PyCharm
@file: music.py
@time: 2018/8/8 16:15
"""
import requests, json
import random, math
from Crypto.Cipher import AES
import base64
import codecs
import os
"""
获取歌曲地址:https://music.XXX.com/weapi/song/enhance/player/url?csrf_token=429d8812f4449bb9acb60e7647113999
"""
class Spider(object):
def __init__(self):
self.headers = {
'Accept': '*/*',
'Accept-Encoding': 'gzip, deflate, sdch',
'Accept-Language': 'zh-CN,zh;q=0.8,en;q=0.6',
'Connection': 'keep-alive',
'Content-Type': 'application/x-www-form-urlencoded',
'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:58.0) Gecko/20100101 Firefox/58.0',
'Cookie': '_ntes_nnid=2da511387474575b77a1e0a13d6df57e,1527507977129; _ntes_nuid=2da511387474575b77a1e0a13d6df57e; vinfo_n_f_l_n3=2e40f7fc7366d16d.1.0.1527507977156.0.1527508882506; usertrack=ezq0plswU1Wdn48dA1XZAg==; _ga=GA1.2.660826221.1529893720; __f_=1532395985802; _iuqxldmzr_=32; __utmz=94650624.1534308847.1.1.utmcsr=(direct)|utmccn=(direct)|utmcmd=(none); WM_TID=Z1Jm%2FrA9KHL%2BHxOBomtGeqTrwVoLDJtd; __utmc=94650624; playerid=19834031; JSESSIONID-WYYY=xMEDtoZO%2BiRzkY3QR%5ChVyupwUBwFivY%2BBAyCPJNlEcmafmm94pa%2BquYglywlQBWN4gKk90XO0Dlx1JCU%2BJ3CmBnV8jHBu5Rzj%2BE%5CcvpBRf%2B%2FI%2BUx71SY5lEsfeJKD6SpzZNCw%2Bae%5Ccnl%5CGv7diN8FZ3Hshs6Bh9Aiooh6sjZkafmwztx%3A1534325997512; __utma=94650624.660826221.1529893720.1534319610.1534324198.4; __utmb=94650624.2.10.1534324198; WM_NI=ZzfxoKxGKsmy3YW9fXsRoCollXv7f8VCQELJt4javuXbEgmayUVzE2FcppvHW174lpq1iEeIUNhLS69AeEf%2B%2Fsf5BGaLSIbLfmBZDUozXUnTXRxo2%2BpZmH79ev2gI8%2FqdTI%3D; WM_NIKE=9ca17ae2e6ffcda170e2e6eeb5ec398bbcbaa8f3549aeaa494e763938aa68dc952f68d8585b77aba95b8baf22af0fea7c3b92a9aa6aa99ee41bc998594f073f18799dae554b18ea1a4ee68b088bad8e534969d9fa6cf42b8eca682f57f9cbe8b88f06bbb8b9a9bc83a86bdc091f54495eff9d5ef7cb3efa7a6e8439792a8add23efb9faba6e521edadaad6c14da3949daae148a6b38ebbc75fada698b6ed609c8eb890b121b486a3a9b633a7aafe88cc34edafacb5cc37e2a3'
}
def __get_songs(self, name):
d = json.dumps(
{"hlpretag": "<span class=\"s-fc7\">", "hlposttag": "</span>", "s": name, "type": "1", "offset": "0",
"total": True, "limit": 30, "csrf_token": ""})
wyy = WangYiYun(d) # 要搜索的歌曲名在这里
data = wyy.get_data()
url = 'https://music.XXX.com/weapi/cloudsearch/get/web?csrf_token='
response = requests.post(url, data=data, headers=self.headers).json()
return response['result']
def __get_mp3(self, id):
d = json.dumps({'ids': "[{}]".format(id), 'br': 320000, 'csrf_token': ""})
wyy = WangYiYun(d)
data = wyy.get_data()
url = 'https://music.XXX.com/weapi/song/enhance/player/url?csrf_token='
response = requests.post(url, data=data, headers=self.headers).json()
print(response['code'])
if response['code'] == -460:
return ''
return response['data'][0]['url']
def __download_mp3(self, url, filename):
"""下载mp3"""
abspath = os.path.abspath('.') # 获取绝对路径
os.chdir(abspath)
response = requests.get(url, headers=self.headers).content
path = os.path.join(abspath, filename)
with open('{}.mp3'.format(filename), 'wb') as f:
f.write(response)
print('下载完毕,可以在{}.mp3查看'.format(path))
def __print_info(self, songs):
"""打印歌曲需要下载的歌曲信息"""
songs_list = []
for num, song in enumerate(songs):
print(num, '歌曲名字:', song['name'], '作者:', song['ar'][0]['name'])
songs_list.append((song['name'], song['id']))
return songs_list
def run(self):
while True:
name = input('请输入你需要下载的歌曲:')
songs = self.__get_songs(name)
if songs['songCount'] == 0:
print('没有搜到此歌曲,请换个关键字')
else:
songs = self.__print_info(songs['songs'])
num = input('请输入需要下载的歌曲,输入左边对应数字即可')
if num == 'q':
pass
else:
url = self.__get_mp3(songs[int(num)][1])
if not url:
print('歌曲需要收费,下载失败')
else:
filename = songs[int(num)][0]
self.__download_mp3(url, filename)
flag = input('如需继续可以按任意键进行搜歌,否则按0结束程序')
if flag == '0':
break
print('程序结束!')
class WangYiYun(object):
def __init__(self, d):
self.d = d
self.e = '010001'
self.f = "00e0b509f6259df8642dbc35662901477df22677ec152b5ff68ace615bb7b725152b3ab17a876aea8a5a" \
"a76d2e417629ec4ee341f56135fccf695280104e0312ecbda92557c93870114af6c9d05c4f7f0c3685b7a46be" \
"e255932575cce10b424d813cfe4875d3e82047b97ddef52741d546b8e289dc6935b3ece0462db0a22b8e7"
self.g = "0CoJUm6Qyw8W8jud"
self.random_text = self.get_random_str()
def get_random_str(self):
"""js中的a函数"""
str = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'
res = ''
for x in range(16):
index = math.floor(random.random() * len(str))
res += str[index]
return res
def aes_encrypt(self, text, key):
iv = '0102030405060708' # 偏移量
pad = 16 - len(text.encode()) % 16 # 使加密信息的长度为16的倍数,要不会报下面的错
# 长度是16的倍数还会报错,不能包含中文,要对他进行unicode编码
text = text + pad * chr(pad) # Input strings must be a multiple of 16 in length
encryptor = AES.new(key, AES.MODE_CBC, iv)
msg = base64.b64encode(encryptor.encrypt(text)) # 最后还需要使用base64进行加密
return msg
def rsa_encrypt(self, value, text, modulus):
'''进行rsa加密'''
text = text[::-1]
rs = int(codecs.encode(text.encode('utf-8'), 'hex_codec'), 16) ** int(value, 16) % int(modulus, 16)
return format(rs, 'x').zfill(256)
def get_data(self):
# 这个参数加密两次
params = self.aes_encrypt(self.d, self.g)
params = self.aes_encrypt(params.decode('utf-8'), self.random_text)
enc_sec_key = self.rsa_encrypt(self.e, self.random_text, self.f)
return {
'params': params,
'encSecKey': enc_sec_key
}
def main():
spider = Spider()
spider.run()
if __name__ == '__main__':
main()