作者:Jason zhou  Python爱好者社区专栏作者
博客地址:http://www.zhouzying.cn/author/jason-zhou

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

一,首先分析数据的请求方式

网易云音乐歌曲页面的URL形式为https://music.163.com/#/song?id=歌曲id号,这里我用Delacey的Dream it possible 为例进行讲解,它的URL为https://music.163.com/#/song?id=38592976.接下来开始分析数据的请求方式.

由于网易云音乐的评论是通过Ajax传输,我们打开浏览器的开发者工具(检查元素),选中控制面板中的Network,再点击XHR(捕获ajax数据),然后点击左上角的重新加载,会看到下面图片中的数据请求列表

点击R_SO_4_38592976?csrf_token=cdee144903c5a32e6752f50180329fc9这一行,再点击Preview

发现我们所需要的数据就在这json格式的数据中,其中comments中是第一页的全部评论,一共20条,hotcomments是精彩评论一共有15条,每首歌曲只有第一页评论才有精彩评论.接着看一下它的请求头,点击Headers

我们发现的它是个post请求,向下滑你会发现这个post请求还带有数据

这些数据都是经过加密处理的,因此我们需要分析它的加密过程来生成相应的参数,然后把加密后的参数加到post请求中才能获取到我们需要的评论数据.

二,分析加密过程

通过断点调试发现params和encSecKey是由js脚本中的window.asrsea()函数生成的.

我们发现window.asrsea()函数有4个参数,在浏览器的js控制台分别对这四个参数进行调试:

后面三个参数是定值,只有第一个参数是控制评论页面偏移量的参数,它是一个变量.笔者经过分析发现第一个参数的形式是:

{"rid":"R_SO_4_38592976","offset":"0","total":"True","limit":"20","csrf_token":""}

下面我来详细讲解这个变量的发现过程:

首先找到core_dfe56728795d119e4d476fd09ea2dc51.js这个js脚本,然后将断点打在第12973行,点击第一页评论,页面加载到断点处便停止了

然后按下电脑的Esc键打开js控制台,输入i1x,查看第一个变量

这是第一页的i1x的值,接下来看第二页的(需要点击第2页,然后输入i1x的值):

再看第3页:

再看第4页:

通过这几页的分析,我们可以得到i1x值的变化规律,且可以得到它的一般形式:

{"rid":"R_SO_4_38592976","offset":"0","total":"True","limit":"20","csrf_token":""}

offset和limit是必选参数,其他参数是可选的,其他参数不影响data数据的生成,offset (页面偏移量) = (页数-1) * 20, 注意limit最大值为100,当设为100时,获取第二页时,默认前一页是20个评论,也就是说第二页最新评论有80个,有20个是第一页显示的.因此我们可以构造第一个参数为:

# 偏移量,page是页数
offset = (page-1) * 20
msg = '{"offset":' + str(offset) + ',"total":"True","limit":"20","csrf_token":""}'

接下来,我们来看一下window.asrsea()函数的整个加密过程:

!function() {// 函数a生成长度为16的随机字符串function a(a) {var d, e, b = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789", c = "";for (d = 0; a > d; d += 1)e = Math.random() * b.length,e = Math.floor(e),c += b.charAt(e);return c}// 函数b实现AES加密function b(a, b) {var c = CryptoJS.enc.Utf8.parse(b), d = CryptoJS.enc.Utf8.parse("0102030405060708"), e = CryptoJS.enc.Utf8.parse(a), f = CryptoJS.AES.encrypt(e, c, {iv: d,mode: CryptoJS.mode.CBC});return f.toString()}// 函数c实现RSA加密function c(a, b, c) {var d, e;return setMaxDigits(131),d = new RSAKeyPair(b,"",c),e = encryptedString(d, a)}function d(d, e, f, g) {var h = {}, i = a(16);return h.encText = b(d, g),h.encText = b(h.encText, i),h.encSecKey = c(i, e, f),h}function e(a, b, d, e) {var f = {};return f.encText = c(a + e, b, d),f}window.asrsea = d,window.ecnonasr = e
}();

window.asrsea()函数就是上面的d函数,现在我们来看函数d:

function d(d, e, f, g) {var h = {}, i = a(16);return h.encText = b(d, g),   // 第一次AES加密h.encText = b(h.encText, i),    // 第二次AES加密h.encSecKey = c(i, e, f),    // RSA加密h}

参数h.encText是经过两次AES加密得到的,h.encSecKey是经过一次RSA加密得到的,其中i是随机生成的长度为16的随机字符串.

三,生成加密参数

首先我们需要生成长度为16的随机字符串,这里我们仿照上面的javascript的实现,用Python生成16位长的随机字符串:

# 生成随机字符串
def generate_random_strs(length):string = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"# 控制次数参数ii = 0# 初始化随机字符串random_strs  = ""while i < length:e = random.random() * len(string)# 向下取整e = math.floor(e)random_strs = random_strs + list(string)[e]i = i + 1return random_strs

接着用Python实现AES加密,这里要用到pycrypto库,先安装好这个库:

pip   install   pycrypto

然后导入加密模块:

from Crypto.Cipher import AES

由于AES加密的明文长度必须是16的倍数,因此我们需要对明文进行必要的填充,以满足它的长度是16的倍数:

# msg是需要加密的明文,如果不是16的倍数则进行填充(paddiing)
padding = 16 - len(msg) % 16
# 这里使用padding对应的单字符进行填充
msg = msg + padding * chr(padding)

AES加密的模式是AES.MODE_CBC,初始化向量iv=’0102030405060708′,具体的AES加密:

# AES加密
def AESencrypt(msg, key):# 如果不是16的倍数则进行填充(paddiing)padding = 16 - len(msg) % 16# 这里使用padding对应的单字符进行填充msg = msg + padding * chr(padding)# 用来加密或者解密的初始向量(必须是16位)iv = '0102030405060708'cipher = AES.new(key, AES.MODE_CBC, iv)# 加密后得到的是bytes类型的数据encryptedbytes = cipher.encrypt(msg)# 使用Base64进行编码,返回byte字符串encodestrs = base64.b64encode(encryptedbytes)# 对byte字符串按utf-8进行解码enctext = encodestrs.decode('utf-8')return enctext

然后是RSA加密.首先我简单介绍一下RSA的加密过程.在RSA中,明文,密钥和密文都是数字.RSA的加密过程可以用下列的公式来表达,这个公式非常的重要,你只有理解了这个公式,才能用Python实现RSA加密.

密文    =    明文E mod  N           (RSA加密)

RSA的密文是对代表明文的数字的E次方求mod N 的结果, 通俗的讲就是将明文和自己做E次乘法,然后将其结果除以N 求余数,这个余数就是密文.

下面来看具体的RSA加密代码实现:

# RSA加密
def RSAencrypt(randomstrs, key, f):# 随机字符串逆序排列string = randomstrs[::-1]# 将随机字符串转换成byte类型数据text = bytes(string, 'utf-8')seckey = int(codecs.encode(text, encoding='hex'), 16)**int(key, 16) % int(f, 16)# 返回整数的小写十六进制形式return format(seckey, 'x').zfill(256)

RSA加密后得到的字符串长为256,如果不够长则进行填充(不足部分在左侧添0).

最后就是获取那两个加密参数:

# 获取参数
def get_params(page):# msg也可以写成msg = {"offset":"页面偏移量=(页数-1) * 20", "limit":"20"},offset和limit这两个参数必须有(js)# limit最大值为100,当设为100时,获取第二页时,默认前一页是20个评论,也就是说第二页最新评论有80个,有20个是第一页显示的# 偏移量offset = (page-1) * 20# offset和limit是必选参数,其他参数是可选的,其他参数不影响data数据的生成,最好还是保留msg = '{"offset":' + str(offset) + ',"total":"True","limit":"20","csrf_token":""}'key = '0CoJUm6Qyw8W8jud'f = '00e0b509f6259df8642dbc35662901477df22677ec152b5ff68ace615bb7b725152b3ab17a876aea8a5aa76d2e417629ec4ee341f56135fccf695280104e0312ecbda92557c93870114af6c9d05c4f7f0c3685b7a46bee255932575cce10b424d813cfe4875d3e82047b97ddef52741d546b8e289dc6935b3ece0462db0a22b8e7'e = '010001'enctext = AESencrypt(msg, key)# 生成长度为16的随机字符串i = generate_random_strs(16)# 两次AES加密之后得到params的值encText = AESencrypt(enctext, i)# RSA加密之后得到encSecKey的值encSecKey = RSAencrypt(i, e, f)return encText, encSecKey

四,获取全部评论

上面我们获取到了两个参数encText和encSecKey,利用这两个参数来构造post表单数据(Form Data),即data的值:

params, encSecKey = get_params(page)
data = {'params': params, 'encSecKey': encSecKey}

歌曲评论的URL为:

url = 'https://music.163.com/weapi/v1/resource/comments/R_SO_4_' + str(songid) + '?csrf_token='

然后把data加到post的参数中去就能获取到json格式的评论数据.

html = requests.post(url, headers=headers, data=data)

至此,获取网易云音乐全部评论的Python爬虫实现原理分析全部完成!若想获取全部代码请上我的Github:获取网易云音乐歌曲全部评论代码

https://github.com/zyingzhou/wangyiyun_music/blob/master/get_comments.py

python爬取歌曲的全部评论相关推荐

  1. python爬取歌曲评论_python 爬取歌曲评论的简单示例

    这篇文章主要为大家详细介绍了python 爬取歌曲评论的简单示例,具有一定的参考价值,可以用来参考一下. 感兴趣python 爬取歌曲评论的简单示例的小伙伴,下面一起跟随512笔记的小编罗X来看看吧. ...

  2. python爬取网易云音乐评论分析_python爬取网易云音乐评论

    本文实例为大家分享了python爬取网易云音乐评论的具体代码,供大家参考,具体内容如下 import requests import bs4 import json def get_hot_comme ...

  3. python爬取b站评论_学习笔记(1):写了个python爬取B站视频评论的程序

    学习笔记(1):写了个python爬取B站视频评论的程序 import requests import json import os table='fZodR9XQDSUm21yCkr6zBqiveY ...

  4. python爬取当当网商品评论

    python爬取当当网商品评论 本案例获取某鞋评论作为例 案例目的: 通过爬取当当网商品评价,介绍通过结合jsonpath和正则表达式获取目标数据的方法. 代码功能: 输入爬取的页数,自动下载保存每页 ...

  5. python爬取苏宁商品评论

    python爬取苏宁商品评论 爬取其他电商物品评论的案例如下: https://blog.csdn.net/coffeetogether/article/details/114296159 https ...

  6. python爬b站评论_学习笔记(1):写了个python爬取B站视频评论的程序

    学习笔记(1):写了个python爬取B站视频评论的程序 import requests import json import os table='fZodR9XQDSUm21yCkr6zBqiveY ...

  7. python爬取歌曲_python爬取网易云音乐热歌榜实例代码

    首先找到要下载的歌曲排行榜的链接,这里用的是: https://music.163.com/discover/toplist?id=3778678 然后更改你要保存的目录,目录要先建立好文件夹,例如我 ...

  8. python爬取网易云音乐评论并进行可视化分析

    2019独角兽企业重金招聘Python工程师标准>>> 前言 今天为大家一个爬取网易云音乐评论的Python案例,并用Python的第三方库来进行可视化分析,生成图表样式,可以清晰地 ...

  9. 阿凡达时隔十年重映,王者归来还是炒冷饭?Python爬取上千条评论并分析

    [CSDN 编者按]<阿凡达>十年后再次重映,果不其然话题量十足,可能这就是神级影片的召唤力吧.在怀旧的氛围中,我们得以重新审阅这部曾经的现象级.划时代的作品. 作者 | 刘早起      ...

最新文章

  1. Coursera课程Python for everyone:chapter 2
  2. 2013年展望:大数据发展十大趋势分析
  3. 【SDL】 如何在RedHat6.5中搭建SDL开发环境
  4. 一个小小的知识点,关于强制类型转换
  5. Lesson 03:运算符与流程控制
  6. c语言 指针 pdf,深入理解c指针 PDF扫描版[33MB]
  7. unit类型是什么?_面试官虚晃一枪:项目中有用过锁吗?能解释一下什么是AQS?...
  8. 程序员出差是去干什么_让我来告诉你,35岁以上的人都在干什么!
  9. null最后如何排序的_LeetCode 148——排序链表
  10. 设置开机ceph自动map rbd块设备
  11. Logback MDC
  12. leetcode 82. 删除排序链表中的重复元素 II(Remove Duplicates from Sorted List II)
  13. 数据库:数据库设计与数据建模及建模工具(PowerDesigner)
  14. 发现一个提供免费英文软件类书籍的网站[xgluxv]
  15. JavaEE个人学习总结
  16. Spring 事务管理高级应用难点剖析: 第 3 部分
  17. 计算机专业英语第12章在线测试答案,计算机专业英语第章在线测试.doc
  18. 每日股市大盘自动复盘(基于聚宽量化投资平台)
  19. SQL优化工具分享-SQL Tuning Expert Pro for Oracle Trial
  20. 计算机键盘音乐好汉歌,好汉歌(刘欢演唱的歌曲)_百度百科

热门文章

  1. 小白量化彩票实战(6)彩票号码中六保五缩水和旋转矩阵
  2. python给列表的N个元素赋值-*表达式
  3. application.yml与bootstrap.yml的区别
  4. 什么是编码?什么是解码?为什么要编码.解码?
  5. 论苹果与安卓系统争霸
  6. SQL Server 2008 R2 安装过程详解
  7. 从事手机软件开发需要掌握什么知识
  8. RewriteCond %{REQUEST_URI}
  9. Code Wars游戏说明
  10. 【响应式】foundation栅格布局的“尝鲜”与“填坑”