当前位置:   article > 正文

python如何实现批量下载网易云音乐?来看看完整项目_python网易云音乐下载

python网易云音乐下载

有很多学习python的小伙伴都一开始被python的爬虫所吸引,那么到底python的爬虫到底是不是那么神乎,小编给大家分享一个实战案例让大家来更具体的了解一下python爬虫。

python如何实现批量下载网易云音乐?来看看完整项目

小编给大家分享一个完整的python实现下载网易云免费的音乐案例。项目代码如下:

  1. # -*- coding:utf-8 -*-
  2. import requests, hashlib, sys, click, re, base64, binascii, json, os
  3. from Crypto.Cipher import AES
  4. from http import cookiejar
  5. """
  6. Website:http://cuijiahua.com
  7. Author:Jack Cui
  8. Refer:https://github.com/darknessomi/musicbox
  9. """
  10. class Encrypyed():
  11. """
  12. 解密算法
  13. """
  14. def __init__(self):
  15. self.modulus = '00e0b509f6259df8642dbc35662901477df22677ec152b5ff68ace615bb7b725152b3ab17a876aea8a5aa76d2e417629ec4ee341f56135fccf695280104e0312ecbda92557c93870114af6c9d05c4f7f0c3685b7a46bee255932575cce10b424d813cfe4875d3e82047b97ddef52741d546b8e289dc6935b3ece0462db0a22b8e7'
  16. self.nonce = '0CoJUm6Qyw8W8jud'
  17. self.pub_key = '010001'
  18. # 登录加密算法, 基于https://github.com/stkevintan/nw_musicbox脚本实现
  19. def encrypted_request(self, text):
  20. text = json.dumps(text)
  21. sec_key = self.create_secret_key(16)
  22. enc_text = self.aes_encrypt(self.aes_encrypt(text, self.nonce), sec_key.decode('utf-8'))
  23. enc_sec_key = self.rsa_encrpt(sec_keyself.pub_keyself.modulus)
  24. data = {'params': enc_text, 'encSecKey': enc_sec_key}
  25. return data
  26. def aes_encrypt(self, text, secKey):
  27. pad = 16 - len(text) % 16
  28. text = text + chr(pad) * pad
  29. encryptor = AES.new(secKey.encode('utf-8'), AES.MODE_CBC, b'0102030405060708')
  30. ciphertext = encryptor.encrypt(text.encode('utf-8'))
  31. ciphertext = base64.b64encode(ciphertext).decode('utf-8')
  32. return ciphertext
  33. def rsa_encrpt(self, text, pubKey, modulus):
  34. text = text[::-1]
  35. rs = pow(int(binascii.hexlify(text), 16), int(pubKey, 16), int(modulus, 16))
  36. return format(rs, 'x').zfill(256)
  37. def create_secret_key(selfsize):
  38. return binascii.hexlify(os.urandom(size))[:16]
  39. class Song():
  40. """
  41. 歌曲对象,用于存储歌曲的信息
  42. """
  43. def __init__(self, song_id, song_name, song_num, song_url=None):
  44. self.song_id = song_id
  45. self.song_name = song_name
  46. self.song_num = song_num
  47. self.song_url = '' if song_url is None else song_url
  48. class Crawler():
  49. """
  50. 网易云爬取API
  51. """
  52. def __init__(self, timeout=60, cookie_path='.'):
  53. self.headers = {
  54. 'Accept''*/*',
  55. 'Accept-Encoding''gzip,deflate,sdch',
  56. 'Accept-Language''zh-CN,zh;q=0.8,gl;q=0.6,zh-TW;q=0.4',
  57. 'Connection''keep-alive',
  58. 'Content-Type''application/x-www-form-urlencoded',
  59. 'Host''music.163.com',
  60. 'Referer''http://music.163.com/search/',
  61. 'User-Agent''Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36'
  62. }
  63. self.session = requests.Session()
  64. self.session.headers.update(self.headers)
  65. self.session.cookies = cookiejar.LWPCookieJar(cookie_path)
  66. self.download_session = requests.Session()
  67. self.timeout = timeout
  68. self.ep = Encrypyed()
  69. def post_request(self, url, params):
  70. """
  71. Post请求
  72. :return: 字典
  73. """
  74. data = self.ep.encrypted_request(params)
  75. resp = self.session.post(url, data=data, timeout=self.timeout)
  76. result = resp.json()
  77. if result['code'] != 200:
  78. click.echo('post_request error')
  79. else:
  80.   return result
  81. def search(selfsearch_contentsearch_typelimit=9):
  82. """
  83. 搜索API
  84. :params search_content: 搜索内容
  85. :params search_type: 搜索类型
  86. :params limit: 返回结果数量
  87. :return: 字典.
  88. """
  89. url = 'http://music.163.com/weapi/cloudsearch/get/web?csrf_token='
  90. params = {'s'search_content'type'search_type'offset'0'sub''false''limit'limit}
  91. result = self.post_request(url, params)
  92. return result
  93. def search_song(self, song_name, song_num, quiet=Truelimit=9):
  94. """
  95. 根据音乐名搜索
  96. :params song_name: 音乐名
  97. :params song_num: 下载的歌曲数
  98. :params quiet: 自动选择匹配**优结果
  99. :params limit: 返回结果数量
  100. :return: Song独享
  101. """
  102. result = self.search(song_name, search_type=1limit=limit)
  103. if result['result']['songCount'<= 0:
  104. click.echo('Song {} not existed.'.format(song_name))
  105. else:
  106. songs = result['result']['songs']
  107. if quiet:
  108. song_id, song_name = songs[0]['id'], songs[0]['name']
  109. song = Song(song_id=song_id, song_name=song_name, song_num=song_num)
  110. return song
  111. def get_song_url(self, song_id, bit_rate=320000):
  112. """
  113. 获得歌曲的下载地址
  114. :params song_id: 音乐ID.
  115. :params bit_rate: {'MD 128k': 128000, 'HD 320k': 320000}
  116. :return: 歌曲下载地址
  117. """
  118. url = 'http://music.163.com/weapi/song/enhance/player/url?csrf_token='
  119. csrf = ''
  120. params = {'ids': [song_id], 'br'bit_rate, 'csrf_token': csrf}
  121. result = self.post_request(url, params)
  122. # 歌曲下载地址
  123. song_url = result['data'][0]['url']
  124. # 歌曲不存在
  125. if song_url is None:
  126. click.echo('Song {} is not available due to copyright issue.'.format(song_id))
  127. else:
  128. return song_url
  129. def get_song_by_url(self, song_url, song_name, song_num, folder):
  130. """
  131. 下载歌曲到本地
  132. :params song_url: 歌曲下载地址
  133. :params song_name: 歌曲名字
  134. :params song_num: 下载的歌曲数
  135. :params folder: 保存路径
  136. """
  137. if not os.path.exists(folder):
  138. os.makedirs(folder)
  139. fpath = os.path.join(folder, str(song_num) + '_' + song_name + '.mp3')
  140. if sys.platform == 'win32' or sys.platform == 'cygwin':
  141. valid_name = re.sub(r'[<>:"/\|?*]''', song_name)
  142. if valid_name != song_name:
  143. click.echo('{} will be saved as: {}.mp3'.format(song_name, valid_name))
  144. fpath = os.path.join(folder, str(song_num) + '_' + valid_name + '.mp3')
  145. if not os.path.exists(fpath):
  146. resp = self.download_session.get(song_url, timeout=self.timeout, stream=True)
  147. length = int(resp.headers.get('content-length'))
  148. label = 'Downloading {} {}kb'.format(song_name, int(length/1024))
  149. with click.progressbar(length=length, label=label) as progressbar:
  150. with open(fpath, 'wb'as song_file:
  151. for chunk in resp.iter_content(chunk_size=1024):
  152. if chunk:
  153. song_file.write(chunk)
  154. progressbar.update(1024)
  155. class Netease():
  156. """
  157. 网易云音乐下载
  158. """
  159. def __init__(self, timeout, folder, quiet, cookie_path):
  160. self.crawler = Crawler(timeout, cookie_path)
  161. self.folder = '.' if folder is None else folder
  162. self.quiet = quiet
  163. def download_song_by_search(self, song_name, song_num):
  164. """
  165. 根据歌曲名进行搜索
  166. :params song_name: 歌曲名字
  167. :params song_num: 下载的歌曲数
  168. """
  169. try:
  170. song = self.crawler.search_song(song_name, song_num, self.quiet)
  171. except:
  172. click.echo('download_song_by_serach error')
  173. # 如果找到了音乐, 则下载
  174. if song != None:
  175. self.download_song_by_id(song.song_id, song.song_name, song.song_num, self.folder)
  176. def download_song_by_id(self, song_id, song_name, song_num, folder='.'):
  177. """
  178. 通过歌曲的ID下载
  179. :params song_id: 歌曲ID
  180. :params song_name: 歌曲名
  181. :params song_num: 下载的歌曲数
  182. :params folder: 保存地址
  183. """
  184. try:
  185. url = self.crawler.get_song_url(song_id)
  186. # 去掉非法字符
  187. song_name = song_name.replace('/''')
  188. song_name = song_name.replace('.''')
  189. self.crawler.get_song_by_url(url, song_name, song_num, folder)
  190. except:
  191. click.echo('download_song_by_id error')
  192. if __name__ == '__main__':
  193. timeout = 60
  194. output = 'Musics'
  195. quiet = True
  196. cookie_path = 'Cookie'
  197. netease = Netease(timeout, output, quiet, cookie_path)
  198. music_list_name = 'music_list.txt'
  199. # 如果music列表存在, 那么开始下载
  200. if os.path.exists(music_list_name):
  201. with open(music_list_name, 'r'as f:
  202. music_list = list(map(lambda x: x.strip(), f.readlines()))
  203. for song_num, song_name in enumerate(music_list):
  204. netease.download_song_by_search(song_name,song_num + 1)
  205. else:
  206. click.echo('music_list.txt not exist.')

以上就是如何使用python代码爬取下载网易云免费的音乐案例了。不过要提醒广大开发者,此行为可能会收到网易云音乐的“律师函”

关于Python技术储备

学好 Python 不论是就业还是做副业赚钱都不错,但要学会 Python 还是要有一个学习规划。最后大家分享一份全套的 Python 学习资料,给那些想学习 Python 的小伙伴们一点帮助!

一、Python所有方向的学习路线

Python所有方向的技术点做的整理,形成各个领域的知识点汇总,它的用处就在于,你可以按照上面的知识点去找对应的学习资源,保证自己学得较为全面。

在这里插入图片描述

二、Python必备开发工具

三、Python视频合集

观看零基础学习视频,看视频学习是最快捷也是最有效果的方式,跟着视频中老师的思路,从基础到深入,还是很容易入门的。

四、实战案例

光学理论是没用的,要学会跟着一起敲,要动手实操,才能将自己的所学运用到实际当中去,这时候可以搞点实战案例来学习。

五、Python练习题

检查学习结果。

六、面试资料

我们学习Python必然是为了找到高薪的工作,下面这些面试题是来自阿里、腾讯、字节等一线互联网大厂最新的面试资料,并且有阿里大佬给出了权威的解答,刷完这一套面试资料相信大家都能找到满意的工作。

 最后祝大家天天进步!!

上面这份完整版的Python全套学习资料已经上传至CSDN官方,朋友如果需要可以直接微信扫描下方CSDN官方认证二维码免费领取【保证100%免费】。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小桥流水78/article/detail/876033
推荐阅读
相关标签
  

闽ICP备14008679号