【Python/爬虫】爬取网易云音乐评论区热评(练习)

文章目录

  • 【Python/爬虫】爬取网易云音乐评论区热评(练习)
  • 前言
  • 一、分析网页需求
  • 二、找到原值和加密函数
  • 三、分析加密函数的运作方式
    • 1.获取encSecKey的函数
    • 2.获取encText的函数
  • 四、请求页面和结果
  • 五、完整代码
  • 总结

前言

之前在b站看网课学习爬虫,正好老师讲了一个案例,爬取PC端网易云音乐一首歌的热评,觉得很有趣,就记录下来。
接下来,将以许嵩的《雅俗共赏》评论区为例。

一、分析网页需求

首先,打开《雅俗共赏》网页,看一眼评论区有啥内容,再右键点开“查看页面源代码”,看看能否直接在源码中找到评论区的内容。

我这边就不放图片了,找一下可以发现,页面源代码中并没有评论区的内容,再右键“检查”,打开开发者工具的“元素”栏,可以找到评论区的内容。
(小技巧,点击开发者工具左上角的小箭头,再点击网页上内容,就可以确定网页内容在代码中的位置)

这点说明,评论区的内容是通过js等手段和前端静态代码整合在一起的,我们需要通过抓包,来找到评论区的内容。

打开网络栏,选取“Fetch/XHR”限制,刷新网页,可以得到很多包,查看他们的预览,一个包一个包往下找,可在“get?”包里面找到我们想要找的热评。

点开表头分析,发现是POST请求,就要找它的表单数据,点开Payload,发现,表单数据中的两个参数的值是很奇怪的乱码。


这就意味着,网易对表单数据的原值进行了加密,而我们要做的事有两件,找到表单数据未加密数据params和encSecKey的原值,并模拟网易对原值的加密过程去请求网页。

二、找到原值和加密函数

点开“发起程序”可以请求调用堆栈,从下往上是浏览器请求数据的前后顺序。
我们可以知道,一开始的请求是用表单数据的原值,在某个请求后,被加密。


点开最上面那个请求,通过添加断点刷新网页,就可以得到请求的数据,在右边的“作用域”中,找到request中的data以及url,确定你请求的数据是来自于我们想要的(get?)url。如果url中没有get,通过蓝色的小三角刷新即可。找到(get?)url的请求后,可以通过调用堆栈往下找,对比data的值,以及其他数据,寻找疑似未加密的原值。

直接快进。
在其中一个请求中,而且我们能看到,data的数据换成了比较易于理解的数据,看起来像rid=参数,threadId=参数等的拼接起来的,且在该请求中发现i6c下面有非常疑似表单数据的原值,且能和data对应上(i6c数据拼接起来就是data的数据)。

上一个查看的请求中的data还是乱码,这个请求中就有,我们怀疑上一个查看的请求中含有加密函数。

点开上一个请求“u6o”我们能发现以下数据,bUM2x中有两个参数encSecKey和encText,data还是乱码,但是data的开头和encText开头有点像,且i6c的数据也在。我们将分析左边的代码,确定i6c中的数据是否是原值,且找到加密函数。

在蓝条上面的一段函数中分析,我们可以清晰到这么两条代码。
一个是bUM2x = window.asrsea(),中有调用了i6c的值,下面那条就是data,以及我们要找的两个参数:
params 对应bUM2x.encText 和 encSecKey对应bUM2x.encSecKey
我们就可以断定,window.asrsea()就是我们要找的加密函数,而i6c中的值就是我们要找的原始数据。

三、分析加密函数的运作方式

现将原始数据贴到pycharm里面等待

data = {"csrf_token": "","cursor": "-1","offset": "0","orderType": "1","pageNo": "1","pageSize": "20","rid": "R_SO_4_411214279","threadId": "R_SO_4_411214279"
}
## params: bUM2x.encText,
## encSecKey: bUM2x.encSecKey

接下来就来找,window.asrsea()是如何定义的。
在开发者工具的搜索栏里面搜索window.asrsea。

可以看到,只有两条,一条是上面画出来,一条就是我们要找的,点击window.asrsea=d那条跳转到详细的信息。

我们可以看到,d也是一个函数,d函数和函数a,c,d都有关系,所以四个函数需要一起分析。

首先看function dwindow.asrsea

我们可以看到,window.asrsea也是d函数的执行方式,window.asrsea的四个参数对应d中的d,e,f,g的四个形参。
则,
d = JSON.stringify(i6c),即就是data原数据的json格式,d=data
e = bsG7z(…),一个很奇怪的东西,但是我们可以在控制台内运行这句话,可以发现,是个定值,所以可以确定,e='010001'

后面的f和g都可以在控制台中运行,且也是定值:
f = '00e0b509f6259df8642dbc35662901477df22677ec152b5ff68ace615bb7b725152b3ab17a876aea8a5aa76d2e417629ec4ee341f56135fccf695280104e0312ecbda92557c93870114af6c9d05c4f7f0c3685b7a46bee255932575cce10b424d813cfe4875d3e82047b97ddef52741d546b8e289dc6935b3ece0462db0a22b8e7'
g = '0CoJUm6Qyw8W8jud'

可以在代码中写:

data = {"csrf_token": "","cursor": "-1","offset": "0","orderType": "1","pageNo": "1","pageSize": "20","rid": "R_SO_4_411214279","threadId": "R_SO_4_411214279"
}
## params: bUM2x.encText,
## encSecKey: bUM2x.encSecKeyd= data
e ="010001"
f ="00e0b509f6259df8642dbc35662901477df22677ec152b5ff68ace615bb7b725152b3ab17a876aea8a5aa76d2e417629ec4ee341f56135fccf695280104e0312ecbda92557c93870114af6c9d05c4f7f0c3685b7a46bee255932575cce10b424d813cfe4875d3e82047b97ddef52741d546b8e289dc6935b3ece0462db0a22b8e7"
g = "0CoJUm6Qyw8W8jud"
i = "nVMEz65CNmypYp1Q"

(其实这些奇怪的汉字在源代码中是有定义的,有兴趣的可以翻一下)

继续来看d函数

定义了一个h字典,最后输出的就是h两个参数,由之前的代码可知encText和encSecKey正好和我们想要的params和encSeckey分别对应。
又定义了一个i,i的值和a函数有关,那我们来看一下a函数:

函数a很复杂,读一读,又是定义d,e,b的,最后可以由random得出,输出的是一个16位的随机值,这个就很难搞,而且后面的encText和encSecKey的值也和i有关系,看起来好像没有路可以走了。

我们再仔细看一下后面的encText和encSecKey输出代码。

encText有一层嵌套,和b函数有关,有点麻烦。
encSecKey,和c函数有关,而且c里面的参数,i是随机值,e和f都是定值,且和我们的表单原数据data无关,看起来是个切入点,来分析一下c函数,看看有没有什么发现:

c函数里面,定义了d和e,d用了RSA加密,e也是一个函数的处理,但是,如果你在搜索栏里面搜索一下,找一下函数的定义,你会发现,都不含有random,输入是定值,那么c函数输出的也是定值。

也就是说,对于encSecKey的输出,i是随机值,e和f都是定值,最后的输出由i的值来定,只要i确定了,encSecKey就可以确定。

1.获取encSecKey的函数

那么,i该怎么办呢。
我们可以通过在浏览器的代码中添加断点,来截断数据。
将i 定死之后,因为encSecKey和我们的表单数据没有关系,并不需要详细的加密过程,只要我们在相应i 下得到的encSecKey,就是我们想要的。

操作如下:

  1. 由于i=a(16)之后就等到了一个16位的i,我们在这句代码之后添加断点,再点击蓝色小三角输出,得到一个i="CMnnifoCstAlW3C2"。尤其要注意的是,因为i 是随机得到的,你每一次刷新得到的i都不同,这个是分析的时候需要注意的。


2. 然后返回window.asrsea()函数,给两句话都添加断点,然后点击蓝色小三角运行,就能得到i="CMnnifoCstAlW3C2"时的encSecKey

encSecKey="b7c430347f9e9820ac1c4b680edd0587382fedd567e01fa09c85943592bf5e82bfa2b892351b22d9af439bcd8b2e6aff0ef80ffa61d39ed2816627c12099969efa36df7520b3b8ffa5cdd5ff5d3fb275d7a72e4f976503e105b7c973e65870db45ba30e77ccf3321e775c8584269c6eb380e6011aaf2f6c86f7eb4fdd7d1a651"

补充代码块,并编写获得encSecKey的函数,因为和表单数据data无关,我们只需要简单直接返回即可

data = {"csrf_token": "","cursor": "-1","offset": "0","orderType": "1","pageNo": "1","pageSize": "20","rid": "R_SO_4_411214279","threadId": "R_SO_4_411214279"
}
## params: bUM2x.encText,
## encSecKey: bUM2x.encSecKeyd= data
e ="010001"
f ="00e0b509f6259df8642dbc35662901477df22677ec152b5ff68ace615bb7b725152b3ab17a876aea8a5aa76d2e417629ec4ee341f56135fccf695280104e0312ecbda92557c93870114af6c9d05c4f7f0c3685b7a46bee255932575cce10b424d813cfe4875d3e82047b97ddef52741d546b8e289dc6935b3ece0462db0a22b8e7"
g = "0CoJUm6Qyw8W8jud"
i = "CMnnifoCstAlW3C2"def Get_encSecKey( ):##获得encSecKey参数return "b7c430347f9e9820ac1c4b680edd0587382fedd567e01fa09c85943592bf5e82bfa2b892351b22d9af439bcd8b2e6aff0ef80ffa61d39ed2816627c12099969efa36df7520b3b8ffa5cdd5ff5d3fb275d7a72e4f976503e105b7c973e65870db45ba30e77ccf3321e775c8584269c6eb380e6011aaf2f6c86f7eb4fdd7d1a651"
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
import warnings
warnings.filterwarnings('ignore')
import  ssl
ssl._create_default_https_context = ssl._create_unverified_context

2.获取encText的函数

相比较另一个参数来说,这个参数的获取就很困难了。

encText的输出经历了两层b函数。
第一层b函数的参数,d从上面可知,是表单数据data,g是一个定值,我们可以猜测,或许是data作为明文,而g作为密钥加密。
第二层是上一次加密的结果作为明文,而i 这个原本的随机数作为密钥来加密。
现在的好消息是,随机数i 我们找到了一个定值,四个参数都是定值了,我们来分析b函数即可。

解析b函数:

  1. 首先传进来参数a和b,根据上面的猜测,a是明文,b是密钥
  2. 第一句,b经过utf-8编码赋值给局部变量c
  3. 第二句,一串定值的字符串经过utf-8编码赋值给局部变量d
  4. 第四句,a经过utf-8编码赋值给局部变量e
  5. 第五句,重点来了,通过代码,我们可以知道,这是一个AES的加密方式,也就是说,我们之后需要写一个AES的加密方式来加密我们的明文。函数内定义了一个iv,也就是偏移量,是AES加密方式中必须的一个参数,mode也就模式,加密模式有四种,这里采用CBC的加密模式,这里如果对密码学比较熟悉的人应该会很快理解。
  6. 最后,返回一个字符串类型的值。

解析完毕,动手写我们的代码:

首先是,加密过程,我们需要AES的加密,Python有专门的库Pycrpto,需要提前pip安装一下,有些人安装可能会有问题,这个百度自行解决。

AES的加密网上有很多解释,大概注意的点就是:

  1. 我们要现将变量的值经过“utf-8”编码,这是模拟网易加密的过程,然后AES要将明文补充成16的倍数,所以我们需要对明文a进行处理一下(见to_16函数)
  2. 输出时要用base64编码一下,也是AES的加密的要求。
  3. 最后别忘了转成字符串类型(网易模拟需求)
  4. AES编码很容易出现一些报错,如果出现报错,善用搜索引擎解决。
  5. 再写一个获取encText的函数,需要两层加密。

代码如下:

from Crypto.Cipher import AES
from base64 import b64encodedef Get_encText(data):first = enText(data, g) #第一次加密second  = enText(first,i) #第二次加密return second #返回的值即是我们想要的encTextdef to_16(a): #对a进行16位倍数的补充size = 16 - len(a) % 16return a+size*chr(size)def enText(a,b):iv = "0102030405060708" #定义一个偏移量a = to_16(a) #AES编码aes  = AES.new(key=b.encode("utf-8"),mode= AES.MODE_CBC, iv=iv.encode("utf-8")) ##这两步就是aes加密过程bs  = aes.encrypt(a.encode('utf-8'))return  str(b64encode(bs),"utf-8")

你可以打印输出一下,保证代码无误

四、请求页面和结果

接下来就是书写经典的爬虫请求页面代码了。

从开发者工具的页面表头中找到url,并写请求代码,这里面要注意的是,它是“POST”请求,需要对表单数据处理成对应的形式。不知道大家还记不记得,在windou.asrsea()的加密函数,所需要的是表单数据的json格式,所以写的时候,要先将data转为json格式。

代码:

import requests
import json
url = "https://music.163.com/weapi/comment/resource/comments/get?csrf_token="resp=requests.request(url=url,method="POST", data={"params": Get_encText(json.dumps(data)), "encSecKey": Get_encSecKey()
})

最后,将获取的页面转为json格式,将其中的hotcomments提取出来写入一个文件,最后别忘了关闭请求和文件。


str = resp.content.decode()
dic_json = json.loads(str) hotComments= dic_json["data"]["hotComments"]with open("hotcomments.txt","w",encoding='utf-8') as file:for i in hotComments:file.writelines(i["content"]+"\n")print("over!")resp.close()
f.close()

最终得到结果:

代码如下(示例):

五、完整代码

这边将放出完整代码,以供参考。

from Crypto.Cipher import AES
from base64 import b64encode
import requests
import jsondata = {"csrf_token": "","cursor": "-1","offset": "0","orderType": "1","pageNo": "1","pageSize": "20","rid": "R_SO_4_411214279","threadId": "R_SO_4_411214279"
}
## params: bUM2x.encText,
## encSecKey: bUM2x.encSecKeyd= data
e ="010001"
f ="00e0b509f6259df8642dbc35662901477df22677ec152b5ff68ace615bb7b725152b3ab17a876aea8a5aa76d2e417629ec4ee341f56135fccf695280104e0312ecbda92557c93870114af6c9d05c4f7f0c3685b7a46bee255932575cce10b424d813cfe4875d3e82047b97ddef52741d546b8e289dc6935b3ece0462db0a22b8e7"
g = "0CoJUm6Qyw8W8jud"
i = "nVMEz65CNmypYp1Q"def Get_encSecKey( ):##return "51458895f9a066a4d75661d66b61598f9f6eff6c29f936696b706869ea7cc22ed8dc37281a521f02849ac6c199ab0473e865b3fa22627485135883277b02aefa5d3d299e888342ba817a0080a5346f9026ea6be46dd4318cb3c46c0f0077f819a66a04954466286878ac34fbd139b5a1a2f0db4ca16bb4b61173c55899e89605"def Get_encText(data):first = enText(data, g)second  = enText(first,i)return seconddef to_16(a):size = 16 - len(a) % 16return a+size*chr(size)def enText(a,b):iv = "0102030405060708"a = to_16(a)aes  = AES.new(key=b.encode("utf-8"),mode= AES.MODE_CBC, iv=iv.encode("utf-8")) ##这两步就是aes加密过程bs  = aes.encrypt(a.encode('utf-8'))return  str(b64encode(bs),"utf-8")url = "https://music.163.com/weapi/comment/resource/comments/get?csrf_token="resp=requests.request(url=url,method="POST", data={"params": Get_encText(json.dumps(data)),"encSecKey": Get_encSecKey()
})str = resp.content.decode()
dic_json = json.loads(str)hotComments= dic_json["data"]["hotComments"]with open("hotcomments.txt","w",encoding='utf-8') as file:for i in hotComments:file.writelines(i["content"]+"\n")print("over!")resp.close()
file.close()

总结

解析网易的页面代码还是有一定难度的,尤其是和别的网站相比起来,有时还需要一点密码学知识。
顺带一提,这里只获取了一个页面的评论,而网易云评论区采用了局部刷新,可以通过线程池一次性获取多个页面的评论,有兴趣可以研究一下,这里不过多赘述。

【Python/爬虫】爬取网易云音乐评论区热评(练习)相关推荐

  1. python爬虫爬取网易云音乐歌曲_Python网易云音乐爬虫进阶篇

    image.png 年前写过一篇爬网易云音乐评论的文章,爬不了多久又回被封,所以爬下来那么点根本做不了什么分析,后面就再改了下,加入了多线程,一次性爬一个歌手最热门50首歌曲的评论,算是进阶版了- 思 ...

  2. python网易云_用python爬虫爬取网易云音乐

    标签: 使用python爬虫爬取网易云音乐 需要使用的模块 只需要requests模块和os模块即可 开始工作 先去网易云音乐网页版找一下你想要听的歌曲点击进去.按键盘F12打开网页调试工具,点击Ne ...

  3. python爬虫----爬取网易云音乐

    使用python爬虫爬取网易云音乐 目录 使用python爬虫爬取网易云音乐 需要使用的模块 开始工作 运行结果 需要使用的模块 只需要requests模块和os模块即可 开始工作 先去网易云音乐网页 ...

  4. Python爬虫—爬取网易云音乐【热歌榜】歌曲的精彩评论(写入txt文本文件或者MySQL数据库)

      最近在学Python爬虫,看了Blibili爬取网易云音乐评论的视频,视频中是将一首歌的评论存入json文件,我在此代码的基础上扩展了三点:     1.爬取热歌榜200首歌曲的精彩评论:     ...

  5. python爬虫爬取网易云音乐下载_Python爬虫实践-网易云音乐!没有版权又如何!照样爬取!...

    1.前言 最近,网易的音乐很多听不到了,刚好也看到很多教程,跟进学习了一下,也集大全了吧,本来想优化一下的,但是发现问题还是有点复杂,最后另辟捷径,提供了简单的方法啊! 本文主要参考 python编写 ...

  6. python爬虫-爬取网易云音乐歌曲评论

    本文借鉴了@平胸小仙女的知乎回复 https://www.zhihu.com/question/36081767 以及@lyrichu的博客 https://www.cnblogs.com/lyric ...

  7. python爬虫爬取网易云音乐歌曲_如何用爬虫获取网易云音乐歌单中的歌曲?

    --------------------------------- 泻药,以我抓取了307835首网易云音乐的歌单歌曲的经验,讲一下这个问题. 喜欢用Github的可以直接看我的项目源码,代码简单.具 ...

  8. python爬取评论_python爬取网易云音乐评论

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

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

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

  10. python爬取网易云音乐热评_python爬取网易云音乐评论

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

最新文章

  1. 利用循环打印杨辉三角形
  2. MongoDB 安全 checklist 及最优配置模板
  3. 银行系统开发必读的三本书!银行IT开发
  4. jquery 获取 id ,但是id 里面不能有. 这个符号
  5. win10下VS2013+OpenCV2.4.9环境配置
  6. 【kafka】Found a message larger than the maximum fetch size of this consumer on topic
  7. Python2解决的中文乱码问题
  8. C++之默认参数顺序(从右到左)和调用顺序(从左到右)
  9. Linux基础-网络配置
  10. 计算机组成原理 - 基本概念
  11. 得胃病者的饮食原则 养胃及食疗菜谱介绍做法
  12. Git远程库代码回退
  13. 17.keep-alive的作用及用法
  14. 阿里1688产品图片和视频资料下载
  15. 泛微使用代码关联附件
  16. HTTP协议详解你确定不看吗
  17. 安装GitHub代码所需包
  18. Android | HEIF图片格式显示问题
  19. 网站从无到上线都需要什么?
  20. 为什么硬盘总坏?为什么就冠希兄的修好了?

热门文章

  1. 前端JS接收二维数组(列表)的解决办法
  2. [ABAP] MOVE-CORRESPONDING 表
  3. 单端口和双端口的优势_双端口测量和 S参数 - 灵活应用网络分析仪
  4. RMAN delete noprompt obsolete参数研究
  5. 不知道RabbitMQ中Exchange类型Internal是什么意思?这边来~
  6. 干货分享!java进阶视频百度云
  7. 上传遥感图像在地图上自动加载到地图上
  8. python各类地图绘制
  9. 同样是学编程,为什么别人十几岁就成了黑客,而你还在做码农
  10. cityengine笔记