导
语
之前推这篇文章的时候:
有小伙伴留言问下面这个问题:
我寻思着网上的教程不是一大堆么,于是让他自己去知乎或者Github之类的网站上搜索相关关键词以解决这个问题。若干天后这哥们又来留言了:
于是我答应了下来,虽然感觉爬这玩意一点也不有趣,估计这文章的阅读量又要十分惨淡了。不过总不能让关注我的小伙伴为了学习知识把头给搞秃了吧
。那么今天我们就来爬一波网易云个人听歌排行榜吧。OK,废话不多说,让我们愉快地开始吧~
相
关
文
件
关注微信公众号'Charles的皮卡丘',公众号内回复'网易云个人听歌排行榜'获取。
开
发
工
具
Python版本:3.6.4
相关模块:
argparse模块;
DecryptLogin模块;
prettytable模块;
以及一些python自带的模块。
环
境
搭
建
安装Python并添加到环境变量,pip安装需要的相关模块即可。
DecryptLogin安装方式参见(因为经常更新,已经安装过的小伙伴麻烦记得更新一下,否则可能会在新的案例中报错):
该库功能正在通过自己的实际使用不断完善中...
and详细的文档正在路上...
原
理
简
介
这里先发起个投票,看看有多少人想看网易云post参数计算方式的详细原理介绍(因为网上关于网易云post参数破解的文章确实已经烂大街了,我是不太想再啰嗦一遍的),人多的话我可以考虑另外搞篇文章仔细讲解一下:
这篇文章只解决留言区那位小伙伴提出的问题,默认各位已经知道怎么算网易云的post参数或者对原理不感兴趣只想直接调DecryptLogin库来获得post参数。首先,打开网易云,随便找个用户刷新他的听歌排行榜页面并抓包:
发现只要请求类似这样的链接就可以获得该用户的听歌排行榜了:
https://music.163.com/weapi/v1/play/record?csrf_token=90f3b95109118c7335b896e2c24d7ebd返回的数据是这样的:
现在考虑一下怎么构造这个请求,首先是csrf_token这个东西从哪来,之前的文章其实说过,在用户登录后的cookies里可以直接找到该参数,如下图红框所示(当然如果在非登录状态下也能看到目标用户的听歌排行榜,那么这个csrf_token其实是可有可无的):
接着考虑一下怎么算post参数,因为DecryptLogin库里已经写好了,所以我们这里只考虑怎么得到post数据的原文,查看一下initiator,发现Ajax请求的发起方是某core.js文件:
点进去在对应的位置打个断点(也就是需要用post数据的原文来计算最终的post参数的函数那里,至于怎么找到的,全局搜索encSecKey,然后简单分析一下它的计算流程就可以找到了这个函数啦),然后重新运行一下脚本,我们就可以看到post数据的原文啦:
于是我们就可以愉快地开始写代码啦,核心代码如下:
'''获得某用户的听歌排行榜'''def getLeaderboard(self, uid):url = 'https://music.163.com/weapi/v1/play/record?csrf_token=' + self.csrfdata = {'type': '-1','uid': uid,'limit': '1000','offset': '0','total': 'true','csrf_token': self.csrf}res = self.session.post(url, headers=self.headers, data=self.cracker.get(data))res_json = res.json()leader_board = {'weekData': [], 'allData': []}if res_json['code'] == 200:all_data = res_json.get('allData')for item in all_data:songname = item.get('song').get('name')songid = item.get('song').get('id')play_count = item.get('playCount')leader_board['allData'].append([songid, songname, play_count])week_data = res_json.get('weekData')for item in week_data:songname = item.get('song').get('name')songid = item.get('song').get('id')play_count = item.get('playCount')leader_board['weekData'].append([songid, songname, play_count])else:raise RuntimeError('Fail to get leaderboard for %s...' % uid)return leader_board
OK,大功告成~完整源代码详见相关文件。
效
果
展
示
在cmd窗口运行如下命令即可:
python NeteaseListenLeaderboard.py --username 用户名 --password 密码效果如下:
更
多
代码截止2020-02-07测试无误。
其他目前个人较活跃的地方(其他地方别上当了):
Github:https://github.com/CharlesPikachu知乎:https://www.zhihu.com/people/charles_pikachu/activities
微信公众号:
Charles的皮卡丘
哈哈哈哈哈
长按二维码关注