相关免费学习推荐:python视频教程
运行效果
代码
# -*- Coding:utf-8 -*-import requests, hashlib, sys, click, re, base64, binascii, Json, osfrom Crypto.Cipher import AESfrom http import cookiejar"""Website:http://cuijiahua.comAuthor:Jack CuiRefer:https://github.com/darknessomi/musicBox"""class Encrypyed(): """ 解密算法 """ def __init__(self): self.modulus = '00e0b509f6259df8642dbc35662901477df22677ec152b5ff68ace615bb7b725152b3ab17a876aea8a5aa76d2e417629ec4ee341f56135fccf695280104e0312ecbda92557c93870114af6c9d05c4f7f0c3685b7a46bee255932575cce10b424d813cfe4875d3e82047b97ddef52741d546b8e289dc6935b3ece0462db0a22b8e7' self.nonce = '0CoJUm6Qyw8W8jud' self.pub_key = '010001' # 登录加密算法, 基于https://github.com/stkevintan/nw_musicBox脚本实现 def encrypted_request(self, text): text = Json.dumps(text) sec_key = self.create_secret_key(16) enc_text = self.aes_encrypt(self.aes_encrypt(text, self.nonce), sec_key.decode('utf-8')) enc_sec_key = self.rsa_encrpt(sec_key, self.pub_key, self.modulus) data = {'params': enc_text, 'encSecKey': enc_sec_key} return data def aes_encrypt(self, text, secKey): pad = 16 - len(text) % 16 text = text + chr(pad) * pad encryptor = AES.new(secKey.encode('utf-8'), AES.MODE_CBC, b'0102030405060708') ciphertext = encryptor.encrypt(text.encode('utf-8')) ciphertext = base64.b64encode(ciphertext).decode('utf-8') return ciphertext def rsa_encrpt(self, text, pubKey, modulus): text = text[::-1] rs = pow(int(binascii.hexlify(text), 16), int(pubKey, 16), int(modulus, 16)) return format(rs, 'x').zfill(256) def create_secret_key(self, size): return binascii.hexlify(os.urandom(size))[:16]class Song(): """ 歌曲对象,用于存储歌曲的信息 """ def __init__(self, song_ID, song_name, song_num, song_url=None): self.song_ID = song_ID self.song_name = song_name self.song_num = song_num self.song_url = '' if song_url is None else song_urlclass Crawler(): """ 网易云爬取API """ def __init__(self, timeout=60, cookie_path='.'): self.headers = { 'Accept': '*/*', 'Accept-EnCoding': 'gzip,deflate,sdch', 'Accept-Language': 'zh-CN,zh;q=0.8,gl;q=0.6,zh-TW;q=0.4', 'Connection': 'keep-alive', 'Content-Type': 'application/x-www-form-urlencoded', 'Host': 'music.163.com', 'Referer': 'http://music.163.com/search/', 'User-Agent': 'Mozilla/5.0 (windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36' } self.session = requests.Session() self.session.headers.update(self.headers) self.session.cookies = cookiejar.LWPcookieJar(cookie_path) self.download_session = requests.Session() self.timeout = timeout self.ep = Encrypyed() def post_request(self, url, params): """ Post请求 :return: 字典 """ data = self.ep.encrypted_request(params) resp = self.session.post(url, data=data, timeout=self.timeout) result = resp.Json() if result['code'] != 200: click.echo('post_request error') else: return result def search(self, search_content, search_type, limit=9): """ 搜索API :params search_content: 搜索内容 :params search_type: 搜索类型 :params limit: 返回结果数量 :return: 字典. """ url = 'http://music.163.com/weAPI/cloudsearch/get/web?csrf_token=' params = {'s': search_content, 'type': search_type, 'offset': 0, 'sub': 'false', 'limit': limit} result = self.post_request(url, params) return result def search_song(self, song_name, song_num, quIEt=True, limit=9): """ 根据音乐名搜索 :params song_name: 音乐名 :params song_num: 下载的歌曲数 :params quIEt: 自动选择匹配最优结果 :params limit: 返回结果数量 :return: Song独享 """ result = self.search(song_name, search_type=1, limit=limit) if result['result']['songCount'] <= 0: click.echo('Song {} not existed.'.format(song_name)) else: songs = result['result']['songs'] if quIEt: song_ID, song_name = songs[0]['ID'], songs[0]['name'] song = Song(song_ID=song_ID, song_name=song_name, song_num=song_num) return song def get_song_url(self, song_ID, bit_rate=320000): """ 获得歌曲的下载地址 :params song_ID: 音乐ID<int>. :params bit_rate: {'MD 128k': 128000, 'HD 320k': 320000} :return: 歌曲下载地址 """ url = 'http://music.163.com/weAPI/song/enhance/player/url?csrf_token=' csrf = '' params = {'IDs': [song_ID], 'br': bit_rate, 'csrf_token': csrf} result = self.post_request(url, params) # 歌曲下载地址 song_url = result['data'][0]['url'] # 歌曲不存在 if song_url is None: click.echo('Song {} is not available due to copyright issue.'.format(song_ID)) else: return song_url def get_song_by_url(self, song_url, song_name, song_num, folder): """ 下载歌曲到本地 :params song_url: 歌曲下载地址 :params song_name: 歌曲名字 :params song_num: 下载的歌曲数 :params folder: 保存路径 """ if not os.path.exists(folder): os.makedirs(folder) fpath = os.path.join(folder, str(song_num) + '_' + song_name + '.mp3') if sys.platform == 'win32' or sys.platform == 'cygwin': valID_name = re.sub(r'[<>:"/\|?*]', '', song_name) if valID_name != song_name: click.echo('{} will be saved as: {}.mp3'.format(song_name, valID_name)) fpath = os.path.join(folder, str(song_num) + '_' + valID_name + '.mp3') if not os.path.exists(fpath): resp = self.download_session.get(song_url, timeout=self.timeout, stream=True) length = int(resp.headers.get('content-length')) label = 'Downloading {} {}kb'.format(song_name, int(length/1024)) with click.progressbar(length=length, label=label) as progressbar: with open(fpath, 'wb') as song_file: for chunk in resp.iter_content(chunk_size=1024): if chunk: song_file.write(chunk) progressbar.update(1024)class Netease(): """ 网易云音乐下载 """ def __init__(self, timeout, folder, quIEt, cookie_path): self.crawler = Crawler(timeout, cookie_path) self.folder = '.' if folder is None else folder self.quIEt = quIEt def download_song_by_search(self, song_name, song_num): """ 根据歌曲名进行搜索 :params song_name: 歌曲名字 :params song_num: 下载的歌曲数 """ try: song = self.crawler.search_song(song_name, song_num, self.quIEt) except: click.echo('download_song_by_serach error') # 如果找到了音乐, 则下载 if song != None: self.download_song_by_ID(song.song_ID, song.song_name, song.song_num, self.folder) def download_song_by_ID(self, song_ID, song_name, song_num, folder='.'): """ 通过歌曲的ID下载 :params song_ID: 歌曲ID :params song_name: 歌曲名 :params song_num: 下载的歌曲数 :params folder: 保存地址 """ try: url = self.crawler.get_song_url(song_ID) # 去掉非法字符 song_name = song_name.replace('/', '') song_name = song_name.replace('.', '') self.crawler.get_song_by_url(url, song_name, song_num, folder) except: click.echo('download_song_by_ID error')if __name__ == '__main__': timeout = 60 output = 'Musics' quIEt = True cookie_path = 'cookie' netease = Netease(timeout, output, quIEt, cookie_path) music_List_name = 'music_List.txt' # 如果music列表存在, 那么开始下载 if os.path.exists(music_List_name): with open(music_List_name, 'r') as f: music_List = List(map(lambda x: x.strip(), f.readlines())) for song_num, song_name in enumerate(music_List): netease.download_song_by_search(song_name,song_num + 1) else: click.echo('music_List.txt not exist.')
总结相关免费学习推荐:php编程(视频)
以上是内存溢出为你收集整理的实现python批量下载网易云音乐的免费音乐全部内容,希望文章能够帮你解决实现python批量下载网易云音乐的免费音乐所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)