目录

前言

一、准备工作

二、操作步骤

1.分析目标网页,确定目标链接

2.分析调用过程,确定发送请求需要的参数

3.分析加密过程

总结


前言

网络爬虫是一类通过程序的方式获取互联网上的信息的一种十分快捷的方式,你可以用它爬取图片、新闻以及任何你想要获取的互联网上的内容。

网易云歌曲下的评论十分具有艺术特色,我们这次实例的目标就是将歌曲下的精彩评论爬取下来,请看接下来我是如何实现的。


一、准备工作

  1. python 3.7,pycharm
  2. 要爬取的网页:
  3. 需要的python第三方库:
    import requests
    from Crypto.Cipher import AES
    from base64 import b64encode
    import json

    (每个库的作用会在使用时进行详细说明)


二、操作步骤

1.分析目标网页,确定目标链接

  •  首先,我们需要确认目标内容是否在页面源代码里。如果存在,则可以使用BeautifulSoup或Xpath对页面源代码进行目标内容的提取;如果不存在,我们就需要找到显示目标内容的url链接,然后对其进行分析和爬取。

  • 很明显,在目标url的源代码中没有找到我们想要的评论,意味着现在是上述的第二种情况,我们需要找到真正可以显示出评论的url。
  • 通过浏览器上的抓包工具,我们可以看到在打开这个网页时,浏览器自动地向这些url发送了请求,并得到了相应,上图中所指的url则是包含了评论的真正的目标链接。并且在Headers中可以看到,需要传入的参数data是被加密过后的模式,由params和encSecKey构成,所以我们需要得到这两个参数。

2.分析调用过程,确定发送请求需要的参数

  • 在Intiator栏内可以查看浏览器所调用的请求堆栈,通过这个,我们可以知道浏览器进行了那些js脚本的执行过程。我们可以通过分析这些请求,来找寻我们需要的参数。

  • 从最近一次发起的请求开始,可以看到定位到了图中的高亮语句,表明最近一次请求是程序执行了此条语句,所以我们可以在此处设置一个断点,看看当程序执行到这里时会得到什么内容
  • 再次刷新网页,由于刚刚我们设置了断点,所以程序运行到断点时会停下,右边Local栏里则是请求到的信息。在图中可以看到,红色箭头指向的url不是我们的目标url,所以点击黑色箭头指向的按钮,让程序执行下一个操作。
  • 当右边栏里请求的url是我们的目标url时,可以发现发起的request请求中有一个data参数,只有这个参数才能让服务器给我们想要的响应。毫无疑问,此时data里面的数据是被加密过的,那么接下来我们需要做的就是找到data是被如何加密的,随后将加密后的data当作参数发起对目标url的访问,就可以得到我们想要的评论了。
  • 现在我们可以看到在最近一次请求中data参数是已经被加密过的,所以接下来我们需要回溯之前的栈,看一看data是在什么时候进行了什么操作加密的。接下来我点开倒数第二次js脚本,在此设置断点,并将程序执行到请求目标url。可以发现,data在此时还是被加密的,所以我们应该继续往下找,直到找到是在哪一个js脚本中执行的加密操作。
  • 知道找到下图中的脚本时,可以发现它传递的参数data已经不是之前经过加密后的乱码的样式,并且细心的朋友们一定会发现data的值就是下面i0x的值,由此我们可以得出结论,i0x中放的数据就是没有加密前的数据,接下来我们只需要找到加密规律,再将加密后的结果作为参数传递进去就可以得到页面响应。
  • 返回上一个脚本,由上推断可知,data的加密是在上一个脚本中执行的。在上一个脚本中,我们已经得知未加密前的参数就是i0x,所以现在我们在i0x第一次出现时设下断点,在之后的每一句执行后,观察是通过哪一条语句进行的加密。(注意刷新后要保证url是我们的目标url,上面一栏第二个是进行下一语句) 
  • 直到运行到图中的语句,data的值还没有被加密
  • 直到执行到下图中的语句,可以发现出现了encText和encSecKey。回顾开头,我们需要的参数是params和encSecKey,所以从此处已经开始逐渐摸到加密的过程了。图中代码可以发现:buM0X中的encText的值赋给了params,encSecKey赋给了我们最终需要的encSecKey。接下来,我们则需要分析buM0X是怎么产生的,也就是分析window.asrsea这个函数是怎么进行加密的。 

3.分析加密过程

  • 从代码中可以看出,window.asrsea这个函数需要4个参数。分别是未加密前的data,和剩下三个参数。在console工具栏可以将剩下三个参数运行一遍,得到三个固定的值。

  • 接下来我们需要知道window.asrear这个函数是如何进行加密操作的,在代码部分找到另一处window.asrear定义的部分。
  • 下面代码段就是window.asrear。(由于e函数在加密过程中并无实际作用,所以我没有复制上来)
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}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()}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}
  • window.asrear从函数d为入口开始执行,并在d函数中首先调用了a函数。

    1. a函数的作用是生成一段随机的字符串,所以执行结果i就是一段随机值;
  • 接下来,就是生成encSecKey和encText的过程:
  1. 上文提到过:data中paramas的部分就是encText。encText的生成过程是经历了两次b函数的调用,第一次调用是d和g作为参数(d就是未加密前的data,g就是上文提到过的三个值里的最后一个),第二次调用则是将第一次的结果与随机字符串i作为参数传入b函数,生成的部分就是data的params部分。
  • encSecKey:分析函数c:进行了RSA加密操作,不涉及到产生随机数,所以如果我们让参数固定,那么函数c加密后产生的结果一定是不变的。由c调用的参数可知,e和f是上文三个固定值的前两个,如果我们将随机字符串i固定,则函数的结果encSecKey就是固定的。
  • 在图中语句处设置断点,可以看到此时生成的随机字符串i,根据我们的推断,下一行再次调用c函数生成的值在参数固定时是不变的,所以我们可以将encSecKey直接保存下来,此时encSecKey
     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

    部分我们就搞定了。

  • encText:encText经过两次b函数的调用,所以函数b中第一个参数a就是我们的未加密前的数据data,第二个参数时固定值参数g。
  • 函数b中f的生成是经过AES加密的操作,参数e是被加密的数据,c则是密钥(固定参数值g)
 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 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});
  • 下面是代码的讲解:

    import requests   #用于对url发起响应
    from Crypto.Cipher import AES    #用于加密函数中的AES加密操作
    from base64 import b64encode    #用于字符串进行base64编码,并返回字节
    import json   #用于将data转化为字符串模式url = "https://music.163.com/weapi/comment/resource/comments/get"data = {"cursor": "-1","offset": "0","orderType": "1","pageNo": "1","pageSize": "20","rid": "R_SO_4_1430319727","threadId": "R_SO_4_1430319727"
    }# 服务于函数d
    g = "0CoJUm6Qyw8W8jud"
    f = "00e0b509f6259df8642dbc35662901477df22677ec152b5ff68ace615bb7b725152b3ab17a876aea8a5aa76d2e417629ec4ee341f56135fccf695280104e0312ecbda92557c93870114af6c9d05c4f7f0c3685b7a46bee255932575cce10b424d813cfe4875d3e82047b97ddef52741d546b8e289dc6935b3ece0462db0a22b8e7"
    e = "010001"
    i = "2l8EuJuvLirixMmc"   #手动固定,函数中是随机的def get_encSecKey():   # 由于i是固定的,所以经过c函数输出的encSecKey也是固定的return "288bca7fd6e42e24d4549f155b4eb6317ba323b914c9ee8aaccb786cabcd27773aea34d9413b8902f3a1a86e50863cec7e1f872092585cddd432951f210ae078e2f2c6b486c83c210820d5c09c73e2d3f225401ce1f5543f7a6f903c7bdc65b8ea27894c0299f52d801f05aaa6ec61e34082bec0135b9c74dabcabd1e1dba1ab"# 把参数进行加密
    def get_params(data):    # 默认收到的是字符串first = enc_paramas(data, g)     #第一次加密,再将第二次结果与i一起加密second = enc_paramas(first, i)    # 第二次加密return second   # 返回的就是paramas# 将数据长度转化为16的倍数, 为下面加密服务
    def to_16(data):pad = 16 - len(data) % 16data += chr(pad) * padreturn datadef enc_paramas(data, key):iv = "0102030405060708"   # AES加密算法中需要的偏移量data = to_16(data)aes = AES.new(key=key.encode('utf-8'), IV=iv.encode('utf-8'), mode=AES.MODE_CBC)   # 创建加密器bs = aes.encrypt(data.encode('utf-8'))    # 加密,加密的长度必须是16的倍数,”123456789abcchr(4)chr(4)chr(4)chr(4)"return str(b64encode(bs), "utf-8")   # 转化成字符串headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/93.0.4577.82 Safari/537.36 Edg/93.0.961.52"
    }
    resp = requests.post(url, data={"params": get_params(json.dumps(data)),    # 通过函数的加密得到服务器需要的params参数"encSecKey": get_encSecKey()
    })
    # print(resp.text)
    dict = json.loads(resp.text)    # 将得到的内容转化为字典模式
    for i in range(15):print(dict['data']['hotComments'][i]['content'])    #这里时python的基础内容,不太熟悉的朋友可以去回顾一下有关字典和列表的操作

总结

  • 此次爬虫实例将重点放在了函数加密的逻辑分析,获取到评论的url后爬取评论不是本实例重点,重点是如何找到真正的目标url以及分析并解析出需要向服务器发送的参数。

爬取网易云音乐评论,破解网易云加密算法相关推荐

  1. python可视化分析网易云音乐评论_网易云音乐评论催泪刷屏?我用Python抓取了1008328条热评告诉你为什么!...

    文/程天 版面/胡曼君 镝摘 如果再过20年,你还会记得那些年上过的网易云热评吗? 看了那么多的网易云热评,技术思维作祟,我终于也忍不住写个爬虫,用Python通过对1008328条网易云音乐热评的抓 ...

  2. python可视化分析网易云音乐评论_网易云音乐热门评论api分析

    网上有现成的例子我就扒过来了!! title: 网易云评论api分析 date: 2018-12-24 20:54:46 tags: [python] 网易云音乐是个好地方,里面各个都是人才,特别是评 ...

  3. 爬虫之js加密破解抓取网易云音乐评论生成词云

    js破解历程 前言 技能点 界面概况 静态网页 动态网页 页面解析 step1: 找参数 step2:分析js函数 step3:分析参数 step4: 校验 step5:转为python代码 编写爬虫 ...

  4. Python爬虫之js加密破解,抓取网易云音乐评论生成词云

    js破解历程 前言 技能点 界面概况 静态网页动态网页 页面解析 step1: 找参数step2:分析js函数step3:分析参数step4: 校验step5:转为python代码 编写爬虫 很多人学 ...

  5. 网易云音乐评论爬取。

    欢迎关注天善智能,我们是专注于商业智能BI,人工智能AI,大数据分析与挖掘领域的垂直社区,学习,问答.求职一站式搞定! 对商业智能BI.大数据分析挖掘.机器学习,python,R等数据领域感兴趣的同学 ...

  6. python爬取网易云音乐_Python 从零开始爬虫(七)——实战:网易云音乐评论爬取(附加密算法)...

    前言 某宝评论区已经成功爬取了,jd的也是差不多的方法,说实话也没什么好玩的,我是看上它们分析简单,又没加密才拿来试手的.如果真的要看些有趣的评论的话,我会选择网易云音乐,里面汇聚了哲学家,小说家,s ...

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

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

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

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

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

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

  10. python爬取网易云评论最多的歌_python爬取网易云音乐评论

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

最新文章

  1. Windows 技术篇-设置dns提升网速,刷新dns缓存
  2. MIUI 10 Android 原生字体,[教程] MIUI10全局字体替换教程,了解一下?
  3. Together(AtCoder-3524)
  4. error gyp ERR! stack Error: Could not find any Visual Studio installation to use
  5. u盘 连接服务器系统软件,u盘服务器系统
  6. 用Typescript如火如荼地进行angular.js
  7. vs2015 动态链接库问题
  8. mysql行转列sql函数_(转)行变列SQL语句(MSSQL) - jack - 博客园
  9. 如何将开源项目部分代码作为private放在github上?
  10. Chrome中播放时视频编码为.h264和音频编码为acc,采样率为48000,双通道的视频文件时音画不同步
  11. 小米手机运行linux,在Linux系统下使用小米刷机工具:XiaoMiTool V2(XMT2)
  12. 时域采样定理和频域采样定理
  13. 客户分析表格怎么做 财务合并报表培训 5分钟看懂财务报表
  14. Pentaho RestAPI用户角色管理
  15. 分享一下谭文老师的windows驱动开发书籍
  16. 字符串之重复字符统计
  17. 成功在开发板运行vsftpd
  18. 为什么你挖不到漏洞,阿里P8架构师亲授秘籍(五千字详解)
  19. 核磁共振成像脉冲序列——杨正汉(2)
  20. 如何开发一个 WPS 加载项

热门文章

  1. (原创)数字电路设计基础 大一期末 项目 交通灯控制器设计
  2. Cygwin安装教程【超详细】
  3. pentaho安装配置
  4. C#进阶高级程序员开发必知必会:泛型的定义实操案例: 实现堆栈的后进先出功能
  5. 拼多多软件测试开发,拼多多事件对我们业务测试的启发
  6. 单片机STM8S测量电压电路_万用表检测电子电路:电阻测量法,电压测量法
  7. oracle彻底删除dbf文件,ORACLE 删除数据文件模拟灾难恢复
  8. 使用微信提供的云开发实现后端 微信小程序云开发的内容管理CMS
  9. Python--Turtle钟表
  10. Apple Pencil 拆解一代 -1212