本文我将为大家讲解如何用Python爬取网易云音乐歌曲全部评论,希望能帮助到那些想爬取网易云音乐歌曲评论的朋友.网易云音乐歌曲评论的URL:url = 'https://music.163.com/weapi/v1/resource/comments/R_SO_4_' + str(songid) + '?csrf_token=',songid是歌曲的id号,如何获取网易云歌曲id号,请参考:爬取全部热门歌曲及其对应的id号.由于网易云歌曲评论做了混淆加密处理,因此直接用requests获取的方法是行不通的.获取歌曲全部评论的办法只有分析网易云的加密过程,通过构造加密参数来获取歌曲的全部评论.下面我来介绍下如何用Python实现加密参数的构造,并获取歌曲的全部评论.
一,了解加密过程
首先看一下它的post的表单数据的生成过程:
接着看一下它的加密函数:
最后可知encText是经过两次AES加密得到,encSecKey是经过一次RSA加密得到的.
二,分析加密函数
window.asrsea()函数有四个参数,后面三个参数都是定值,只有第一个是变量
这是后面三个参数的值,现在控制台断点调试第一个参数,第一页评论:
第二页:
第三页:
第四页:
因此可以发现i1x的规律:
{"rid":"R_SO_4_1302938992","offset":"0","total":"True","limit":"100","csrf_token":""}
JSON.stringify()函数是将字典转化成字符串形式,这样得到第一个参数的规律为:
'{"rid":"R_SO_4_1302938992","offset":"0","total":"True","limit":"100","csrf_token":""}'
offset和limit是必选参数,其他参数是可选的,其他参数不影响data数据的生成.
三,用Python实现相同的加密算法
Python中有个AES加密库pycrypto,至于RSA加密,我这里讲一下,RSA加密的明文,密钥,密文都是数字,用下面的公式来表示RSA加密:
python实现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)
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
由于AES加密要求明文的长度为16的倍数,因此我们需要对明文长度进行填充.
四,参数的获取
两次AES加密,一次RSA加密,这里我直接写代码:
# 获取参数
def get_params(page):
# msg也可以写成msg = {"offset":"页面偏移量=(页数-1) * 20", "limit":"20"},offset和limit这两个参数必须有(js)
# limit最大值为100,当设为100时,获取第二页时,默认前一页是20个评论,也就是说第二页最新评论有80个,有20个是第一页显示的
# msg = '{"rid":"R_SO_4_1302938992","offset":"0","total":"True","limit":"100","csrf_token":""}'
# 偏移量
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
将加密后参数加到post的表单数据去,然后用requests.post()方法就能获取到含有歌曲评论的json格式的数据.获取完整代码:我的Github
五,参考文章