网易云音乐下载python爬虫(Js破解)

最近做了一个网易云音乐下载的python爬虫,功能就是输入歌曲的名字,程序自动下载网易音乐搜索界面的第一首歌(一般都是原唱排第一位)。本文很适合小白学习,写的很详细,不信的话你试试看!!

需要用到的工具

1.python3.7
2.chrome浏览器
3.sublime编辑器
话不多说,下面开始讲解流程。

主要流程

1.在网易云音乐搜索框中输入“成都”,F12打开开发者模式,搜索框回车,在Network中发现出现了很多响应数据,点进每个响应,切换到右边一栏的Preview。
在web?csrf_token=中我们发现响应result是一个json格式的数据,在songs字段中出现了歌曲列表。


当我们把鼠标放到页面第一首歌曲的上面是,屏幕左下方的链接显示的id刚好就是json数据中id,于是我们找到了歌曲的id,或许有用,接着往下看。
2.
随机点击一首歌进行播放,注意不要点击超链接,那样会跳转页面,点击那个小的播放按钮就可以了。点击播放按钮后左侧导航栏里面会多了几个响应,其中就有一个MP3文件。可以看到浏览器发送了一个GET请求,服务器响应一个mp3文件,如果我们在python程序里面也向Request URL发送一个GET请求,那样不就能下载MP3文件了吗。思路逐渐清晰,于是我们接下来的任务就是寻找到这个URL是从哪里得到的,再重新查看左侧的导航栏,发现在播放歌曲的时候多了一个url?csrf_token=的响应,点进去看Headers,发现是一个POST请求,参数有两个,params和encSecKey,点击Preview,可以看到也是一个json数据,有没有发现我们的响应里面有个url字段,他的地址和我们MP3响应的请求地址是一样的。
很好,大致思路已经有了,就是首先向服务器的url?csrf_token=发送一个POST请求,得到MP3文件的请求地址,再向这个地址发送GET请求就能得到mp3文件。那么问题来了,url?csrf_token=的POST请求的参数怎么办?接着往下看吧!
3.
关闭右侧的导航栏,点击红色箭头所指向的文件,打开后是一个JS文件。点击格式化,这样看的舒服一点。按住Ctrl+F,打开查找搜索框,输入encSecKey。在bLi4m这个变量中含有我们需要的参数。这个bLi4m变量接收的是window.asrsea这个函数返回的数据,将鼠标放到这个函数上面出现一个对话框,是一个d函数,点进去,跳转到了function d()。在function d中多设置几个断点,function d接收d,e,f,g四个参数,我们想要看看着四个参数到底是什么,下面演示断点调试。
4.
我们设置好断点后,刷新页面,js会执行到第一个断点处。
可以看到粉色的是已经执行过的程序变量的值,再次点击红色箭头所指的按钮,程序运行到function d处暂停。在右边的导航栏的Scope中看到d: “{“ids”:”[456185373]",“br”:128000,“csrf_token”:""}"
e: “010001”
f:“00e0b509f6259df8642dbc35662901477df22677ec152b5ff68ace615bb7b725152b3ab17a876aea8a5aa76d2e417629ec4ee341f56135fccf695280104e0312ecbda92557c93870114af6c9d05c4f7f0c3685b7a46bee255932575cce10b424d813cfe4875d3e82047b97ddef52741d546b8e289dc6935b3ece0462db0a22b8e7”
g: “0CoJUm6Qyw8W8jud”。这就是function d的四个参数,解析function d。函数d首相执行函数a,在执行两次b函数,最后执行c函数。a函数就是在一串字符串中随机挑选16个字符组成随机字符串。
b函数刚开始我也没有看懂什么意思,后来学习了一篇文章Python爬虫之网易云音乐下载,大家也可以去看看学习一下。函数b实现的是一个AES加密的过程,至于AES加密大家可以百度看看,有很多文章介绍,python实现这个加密算法也很简单,直接调用函数就可以了。函数b的作用就是将传进去的a,b参数进行加密,其中a是密文,b是偏移量,密钥在函数中给定,是0102030405060708,b函数就说到这里,下面看c函数。c函数实现的是RSA加密,参数a是16位的随机字符串,参数b,c分别是d函数中的e,f常量。好了现在a,b,c函数都已经解析过了,回头来看看d函数,d函数中执行了两次的AES加密,第一次加密的结果作为第二次加密的密文连同16位的随机字符串,再次加密,而RSA加密只执行一次,需要注意的是在整个加密的过程中,随机字符串使用的始终是同一个字符串。到这里为止,整个加密过程基本解析完毕,下面开始上代码。
5.
安装 PyCryptodome库,直接pip install PyCryptodome就行。
生成16位随机字符串,也就是一个for循环的事。

def get_random_str():str = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';random_str = '';for i in range(16):index = random.randint(0,len(str)-1);random_str += str[index];return random_str;

AES加密

def aes_encrypt(text,key):#text是要加密的密文,key是密钥iv = b'0102030405060708';pad = 16 - len(text) % 16;text = text + chr(2) * pad;#这个是将不足16倍数的密文补全到16的倍数,没有这个会报错encryptor = AES.new(key.encode(),AES.MODE_CBC,iv);encryptor_str = encryptor.encrypt(text.encode());#这一定要UTF-8编码result_str = base64.b64encode(encryptor_str).decode();return result_str;

AES要加密的密文是 “{“ids”:”[song_id]",“br”:128000,“csrf_token”:""}",只要将其中的song_id替换成歌曲的id就行了,就是上面说到的POST请求得到的id。
RSA加密

def rsa_encrypt(text):#text是16位的随机字符串pub_key = '010001';#js中的e# js中的fmodulus = '00e0b509f6259df8642dbc35662901477df22677ec152b5ff68ace615bb7b725152b3ab17a876aea8a5aa76d2e417629ec4ee341f56135fccf695280104e0312ecbda92557c93870114af6c9d05c4f7f0c3685b7a46bee255932575cce10b424d813cfe4875d3e82047b97ddef52741d546b8e289dc6935b3ece0462db0a22b8e7'text = text[::-1];result = pow(int(hexlify(text.encode()),16),int(pub_key,16),int(modulus,16));return format(result,'x').zfill(131);

RSA加密的密文是16位的随机字符串,要和AES加密保持一致。
6.
介绍完加密过程,下面介绍获取歌曲id,毕竟我们要实现的是下载任意的歌曲。输入歌曲名字就能下载,要实现这个功能就必须得到id,然后通过上文加密方法,获得params和encSecKey参数发送POST请求回去下载的url。这里我们发现了获取id的url,查看其request请求。同样的这也是一个post请求,参数还是params和encSecKey,和上面加密一样,查看其js文件,进行断点调试,有了上面的经验,这次我们重点查看d函数就行了。可以看到这次d函数传入的参数基本没有变,只有d参数稍有变化,变成了"{“hlpretag”:"<span class=“s-fc7”>",“hlposttag”:"","#/download":"",“s”:“成都”,“type”:“1”,“offset”:“0”,“total”:“true”,“limit”:“30”,“csrf_token”:""}",其中s字段就是我们要搜索的歌曲名字,还是按照前面的加密过程一样得到post参数,到这里整个过程基本结束,下面贴上完整的代码。
7.
程序流程就是,首先输入想要下载歌曲的名字,然后拼接密文字符串进行加密,获得歌曲的id,再通过id获取下载的链接,其中由于获取的歌曲id有很多个,我只选择下载第一个(一般都是原唱),程序写的很简单,但基本功能已经实现,大家可以学习一下。

import random
import requests
from Crypto.Cipher import AES
from binascii import hexlify
import json
import base64
from pprint import pprint
import osheaders = {'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','Cookie':'_iuqxldmzr_=32; _ntes_nnid=3781266ef61a5aa2d7ede27aa0183bc1,1551083564434; _ntes_nuid=3781266ef61a5aa2d7ede27aa0183bc1; WM_TID=OZGc1XNosq1FFVUURUIpkhlLoMCtrNMy; WM_NI=8rKLP6ufZLsNyeHmP9SDIvgYp6Yeuuu9ZGfzbCvvrI%2B%2FXUYhDsvVVFRPPcN1ekPJXIbE%2FYcXpJhEf9dT8jQQUfTaONE8iXIYAb%2F6FvZ0Xr4hoDjDHTgTPQpejvbJ0%2FIHU2Q%3D; WM_NIKE=9ca17ae2e6ffcda170e2e6ee92ef80fbaeb9d8b67b94a88ab2c85e829b9aafee7df4eda58df544a68f00d7ae2af0fea7c3b92afcae85add33eb7ba96adf246bbbb888ed333919c8797e653b4ea9786f87fb7e796a8e572a29dba97f143e9f198b6dc6488adbab7d54e9290a084cd3ba7b5a0abdb43a29be1bae254b496a8a6e533a88cf88bd45b97ba9c82ce4687e8a7b9cc5383bee1d7c57e9af09893b764ad9ca6a5cb60a58ca0b2f36faaaaaeabb3258b989bd3d437e2a3; JSESSIONID-WYYY=%2B0ojNXAeyKT7wKzj1AnD3RXYergSXK5S70VlZwNdlKqvuFDjOfb1Ao2PGtbBUf38RohOpdmBfcMpY3eM2jp5WiRsaJ22nosm%2F1AwqaJgomKkGAY5VfXyM%2BcVUrlgTEZFHaMNUcePUXY05Ks23XgW4yr1gPmb%2FJbtbks9nbC0OUlX82cn%3A1551237928176'};def get_random_str():str = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';random_str = '';for i in range(16):index = random.randint(0,len(str)-1);random_str += str[index];return random_str;def aes_encrypt(text,key):#text是要加密的密文,key是密钥iv = b'0102030405060708';pad = 16 - len(text) % 16;text = text + chr(2) * pad;encryptor = AES.new(key.encode(),AES.MODE_CBC,iv);encryptor_str = encryptor.encrypt(text.encode());result_str = base64.b64encode(encryptor_str).decode();return result_str;def rsa_encrypt(text):#text是16位的随机字符串pub_key = '010001';#js中的e# js中的fmodulus = '00e0b509f6259df8642dbc35662901477df22677ec152b5ff68ace615bb7b725152b3ab17a876aea8a5aa76d2e417629ec4ee341f56135fccf695280104e0312ecbda92557c93870114af6c9d05c4f7f0c3685b7a46bee255932575cce10b424d813cfe4875d3e82047b97ddef52741d546b8e289dc6935b3ece0462db0a22b8e7'text = text[::-1];result = pow(int(hexlify(text.encode()),16),int(pub_key,16),int(modulus,16));return format(result,'x').zfill(131);#b函数,两次AES加密
def get_aes(text,random_str):first_aes = aes_encrypt(text,key='0CoJUm6Qyw8W8jud');#key是固定的,相当于gsecond_aes = aes_encrypt(first_aes,random_str);return second_aes;#获取加密的参数
def get_post_data(text,random_str):params = get_aes(text,random_str);encSecKey = rsa_encrypt(random_str);return {'params':params,'encSecKey':encSecKey};def get_song_list(song_name,random_str):#要加密的字符串text = {"hlpretag":"<span class=s-fc7>","hlposttag":"</span>","s":song_name,"type":"1","offset":"0","total":"true","limit":"50","csrf_token":""};text = json.dumps(text);data = get_post_data(text,random_str);url = 'https://music.163.com/weapi/cloudsearch/get/web?csrf_token=';return post_requests(url,data);def post_requests(url,data):session = requests.Session();session.headers.update(headers);re = session.post(url,data=data);return re.json();def get_song_url(song_id,random_str):#'MD 128k': 128000, 'HD 320k': 320000text = {'ids': [song_id], 'br': 128000, 'csrf_token': ''};text = json.dumps(text);data = get_post_data(text,random_str);url = 'https://music.163.com/weapi/song/enhance/player/url?csrf_token=';return post_requests(url,data);if __name__ == '__main__':random_str = get_random_str();song_name = input('输入歌曲名:')song_list = get_song_list(song_name,random_str);id = song_list['result']['songs'][0]['id'];song_url = get_song_url(id,random_str)['data'][0]['url'];if not os.path.exists(song_name):os.mkdir(song_name);#新建文件夹with open(song_name+'/'+song_name+'.mp3','wb') as f:try:response = requests.get(song_url, timeout=10);except requests.exceptions.ConnectTimeout:#超时重新请求response = requests.get(song_url, timeout=10);f.write(response.content);

我在写程序的时候参考了github上面的一个项目,大家有兴趣也可以去学习一下,地址在这里。

写在最后

这次破解网易云音乐学到了很多小的技能,像js的断点调试,AES和RSA加密,前前后后花了不少的心思,看了很多文档,在这里也向乐于分享自己技术的前辈们致敬!

网易云音乐python爬虫(Js破解)相关推荐

  1. python爬虫api接口,网易云音乐python爬虫api接口

    抓包能力有限,分析了一下网易云音乐的一些api接口,但是关于它很多post请求都是加了密,没有弄太明白.之前在知乎看到过一个豆瓣工程师写的教程,但是被投诉删掉了,请问有网友fork了的吗?因为我觉得他 ...

  2. 网易云音乐python爬虫搜索接口,评论接口,歌词接口

    网易云搜索歌曲,歌曲评论抓取,歌词抓取,仅供参考. 网易云音乐接口分析 网易云接口都是同一套加密代码,不同得API对应不同的请求参数,本文以搜索歌曲API为例子详细介绍加密代码,js AES 加密 搜 ...

  3. Python 网易云音乐评论爬虫

    引言 之前网易云音乐和农夫山泉合作,将热门评论印在农夫山泉上引爆了朋友圈.于是想爬取一下网易云的评论.网上搜了一下,对于网易云评论的爬虫不少,主要参考这篇文章:对网易云音乐参数(params,encS ...

  4. python第三方插件登录网易音乐_GitHub - TomoToTomoT/NeteaseCloudMusic-Python: 网易云音乐--python Api...

    #NeteaseCloudMusic-python 网易云音乐python版Api 开发文档 获取最新评论 req_comments(music_id, page = 1, page_num = 20 ...

  5. python爬虫网易云音乐评论最多的歌_Python网易云音乐评论爬虫,歌曲的全部评论...

    用过网易云音乐听歌的朋友都知道,网易云音乐每首歌曲后面都有很多评论,热门歌曲的评论更是接近百万或者是超过百万条.现在我就来分享一下如何爬取网易云音乐歌曲的全部评论,由于网易云音乐的评论都做了混淆加密处 ...

  6. 『Python』网易云音乐API爬虫(音乐搜索音乐播放)

    前言 永远相信美好的事情即将发生 背景 一直想做一个在线的音乐播放器,这个想法最早可以追溯到做毕设的那会,那时候做了个在线的商城系统, 里面有个在线听歌的模块,其实就是调用大佬们封装好的API进行搜索 ...

  7. 网易云音乐评论爬虫:爬取全部热门歌曲及其对应的id号(附全部代码)

    今天我给大家介绍一下用Python爬取网易云音乐全部歌手的热门歌曲. 由于歌手个人主页的网页源代码中还嵌入了一个子网页(框架源代码里面包含了我们需要的信息),因此我们不能使用requests库来爬取, ...

  8. 网易云音乐评论爬虫(2):歌曲的全部评论

    用过网易云音乐听歌的朋友都知道,网易云音乐每首歌曲后面都有很多评论,热门歌曲的评论更是接近百万或者是超过百万条.现在我就来分享一下如何爬取网易云音乐歌曲的全部评论,由于网易云音乐的评论都做了混淆加密处 ...

  9. 从网易云音乐看爬虫。

    别人有的,我们也要有 看到一些诗意的推文总能自带一些音乐,但是我又不喜欢微信公众号自带的QQ音乐,所以今天来下载一次mp3格式音乐~ 一直在想如何将一个人熟悉或不熟悉的知识通俗易懂的描绘笔下,所以今天 ...

最新文章

  1. Block abstraction view(Create Reference)
  2. java进程与线程_Java多线程笔记(零):进程、线程与通用概念
  3. Windows下修改Git Bash 默认路径
  4. WEB项目 后台接收前端数组
  5. 【安全漏洞】浅谈Bypass Waf (基础-实战)
  6. Python 基础(常用数据结构)
  7. SQLite事务与自增深度分析
  8. 英语学习笔记2019-9-27
  9. Android 系统(163)---Gallery为何有的图片在详细信息里查看其分辨率与实际不一样?
  10. 深度学习入门首推资料--吴恩达深度学习全程笔记分享
  11. 大数据的分析手段有哪几种
  12. 关于session校验在项目中的使用
  13. vim编辑器中常用的命令
  14. binwalk和foremost的使用。
  15. usb接口多少钱_3分钟搞懂USB
  16. 阿铭Linux_网站维护学习笔记20190416
  17. 最近的收获以及清明节的安排
  18. 手把手教你做一个网页
  19. 工程测量gps静态的实训报告_GPS-RTK实战攻略——静态、动态测量的区别和步骤...
  20. Could not find artifact pom:2.0.0 in public

热门文章

  1. 最好的60个国外壁纸网站
  2. 解决spring源码构建时缺失spring-cglib-repack和spring-objenesis-repack问题
  3. PS工作记录——图片元素复制,智能抠图
  4. transition、-moz-transition、-webkit-transition、-o-transition是什么意思?怎样用?
  5. iview可编辑表格组件封装
  6. 【opencv】selective_search函数
  7. 利用PCL库做简单的三维立体图形
  8. C语言——三位数的百位,十位,个位分别输出
  9. python入门和使用
  10. 路由器pppoe服务器无响应,宽带拨号服务器无响应