python爬虫–爬取网易云音乐评论

python爬虫–爬取网易云音乐评论

python爬虫–爬取网易云音乐评论

方1:使用selenium模块,简单粗暴。但是虽然方便但是缺点也是很明显,运行慢等等等。
方2:常规思路:直接去请求服务器

1.简易看出评论是动态加载的,一定是ajax方式。

2.通过网络抓包,可以找出评论请求的的URL

在这里插入图片描述
得到请求的URL
在这里插入图片描述

3.去查看post请求所上传的数据

在这里插入图片描述
显然是经过加密的,现在就需要按着网易的思路去解读加密过程,然后进行模拟加密。

4.首先去查看请求是经过那些js到达服务器的

在这里插入图片描述

5.设置断点:依次对所发送的内容进行观察,找到评论对应的URL

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

6.查找加密函数

在这里插入图片描述

(忽略查找过程)找到:加密函数在
在这里插入图片描述
通过查找,找到加密函数具体位置:
在这里插入图片描述

7.解读加密函数

运用的是AES,模式是:CBC

function a(a) {
    a=16
        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); #取出b中对应位置的字符
        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) #e是数据
          , f = CryptoJS.AES.encrypt(e, c, {
    #c就是加密密钥 
            iv: d, #iv是偏移量
            mode: CryptoJS.mode.CBC # 模式: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) {
    d:数据json串  e:"010001" f:   g = "0CoJUm6Qyw8W8jud"
        var h = {
   }
          , i = a(16); #16位随机值
        return h.encText = b(d, g), g是密钥
        h.encText = b(h.encText, i), #返回的就是params i是密钥
        h.encSecKey = c(i, e, f), #返回的是encSecKey e和f定死,能产生变数的只能是i
        h
    function e(a, b, d, e) {
   
        var f = {
   };
        return f.encText = c(a + e, b, d),
        f
    }
    window.asrsea = d

解读该过程即可:代码有注释。

8.参数如何获得:

 function d(d, e, f, g) {
    d:数据json串  e:"010001" f:   g = "0CoJUm6Qyw8W8jud"


 var bZe2x = window.asrsea(JSON.stringify(i4m), brx6r(["流泪", "强"]), brx6r(Sc1x.md), brx6r(["爱心", "女孩", "惊恐", "大笑"]));

#使用网页控制台:发现都为定值;

在这里插入图片描述

9.这时只需找到某一个i以及它对应的encSecKey 即可完成服务器的验证

在这里插入图片描述
拿到该值之后开始编写代码

全部代码粘贴

#1.找到未加密的参数 #通过函数window.asrsea()进行加密
#2.想办法把参数进行加密,params--->encText encSecKey--->encSecKey

from Cryptodome.Cipher import AES
from base64 import b64encode
import requests,json



e = "010001"
f = "00e0b509f6259df8642dbc35662901477df22677ec152b5ff68ace615bb7b725152b3ab17a876aea8a5aa76d2e417629ec4ee341f56135fccf695280104e0312ecbda92557c93870114af6c9d05c4f7f0c3685b7a46bee255932575cce10b424d813cfe4875d3e82047b97ddef52741d546b8e289dc6935b3ece0462db0a22b8e7"
g = "0CoJUm6Qyw8W8jud"
i = "0hyFaCNAVzOIdoht"

url = 'https://music.163.com/weapi/comment/resource/comments/get?csrf_token='
headers = {
   
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.105 Safari/537.36'
    }

def get_encSecKey():
    return "4022359ea3110bcd034e0160c3b89e5e172fd0110a3cf765d9f366d9fd09840a1f4a4705ac43719fdb8bfeb44d3b92334733061ad10942131184a4dfba0ac9d2cf867b8b6236523c1ca5f44c0d2d82c1c2665a3137a9241c7373539c1aa8e5e9bb9d33dafc764b5d76c2ab34fc94df85e27a934c8a603fa713f2cf38c2b7bbae"

def get_params(data): #data默认是json字符串
    first = enc_params(data,g)
    second = enc_params(first,i)
    return second

def to_16(data):
    pad = 16-len(data)%16
    data +=chr(pad) * pad
    return data

def enc_params(data,key): #加密过程
    iv = "0102030405060708"
    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')) #加密
    return str(b64encode(bs),"utf-8") #转化成字符串

#处理加密过程
''' function a(a) { a=16 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); #取出b中对应位置的字符 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) #e是数据 , f = CryptoJS.AES.encrypt(e, c, { #c就是加密密钥 iv: d, #iv是偏移量 mode: CryptoJS.mode.CBC # 模式: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) { d:数据json串 e:"010001" f: g = "0CoJUm6Qyw8W8jud" var h = {} , i = a(16); #16位随机值 return h.encText = b(d, g), g是密钥 h.encText = b(h.encText, i), #返回的就是params i是密钥 h.encSecKey = c(i, e, f), #返回的是encSecKey e和f定死,能产生变数的只能是i h }'''
if __name__ == '__main__':

    page = int(input('请输入需要爬取的页数:'))
    print('开始爬虫!!!')
    fp = open('./网易云评论.txt', 'w', encoding='utf-8')
    for j in range(1,page+1):
        page_num = str(j*20)
        data = {
   
            'csrf_token': "",
            'cursor': "-1",
            'offset': "0",
            'orderType': "1",
            'pageNo': "1",
            'pageSize': page_num,
            'rid': "R_SO_4_1376142151",
            'threadId': "R_SO_4_1376142151"
        }

        response = requests.post(url,data={
   
            "params":get_params(json.dumps(data)),
            "encSecKey":get_encSecKey()
        },headers=headers)


        result = json.loads(response.content.decode('utf-8'))
        #hotComments
        for hot in range(len(result['data']['hotComments'])):
            fp.write('hotComments' + ' ')
            fp.write('昵称:' + result['data']['hotComments'][hot]['user']['nickname'] + '\n')
            fp.write('评论:' + result['data']['hotComments'][hot]['content'] + '\n')

            if result['data']['hotComments'][hot]['user']['vipRights'] == None:
                fp.write('vip:yes' + '\n')
            else:
                fp.write('vip:no' + '\n')
            fp.write('点赞数' + str(result['data']['hotComments'][hot]['likedCount']) + '\n')
            fp.write('-------------------------------------' + '\n')

        #print(result['data']['hotComments'][1]['user']['nickname'])

        #comments
        for r in range(20):
            fp.write('comments')
            fp.write('昵称:'+result['data']['comments'][r]['user']['nickname']+'\n')
            fp.write('评论:'+result['data']['comments'][r]['content']+'\n')

            if result['data']['comments'][r]['user']['vipRights'] == None:
                fp.write('vip:yes'+'\n')
            else:
                fp.write('vip:no'+'\n')
            fp.write('点赞数'+str(result['data']['comments'][r]['likedCount'])+'\n')
            fp.write('-------------------------------------'+'\n')
    print('爬取完毕!!!')



效果图

在这里插入图片描述

感想

通过这次爬虫实验,在爬取的过程中,遇到各种困难,收货很多。掌握遇到加密,该如何处理的步骤,以及拓宽自己的思路,去运用各种工具。以及各种自己想不到的思路。最起码,下次遇到如此加密的数据获取,心里有了一些底气。
也了解了大互联网公司对数据进行加密的一种方式,以及网页运作的更深一步的了解,受益颇多。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/100084.html原文链接:https://javaforall.net

赞 (0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • ArrayList底层实现原理「建议收藏」

    ArrayList底层实现原理「建议收藏」ArrayList简介ArrayList是我们开发中非常常用的数据存储容器之一,其底层是数组实现的,我们可以在集合中存储任意类型的数据,ArrayList是线程不安全的,非常适合用于对元素进行查找,效率非常高。源码分析创建了一个大小为0的数组,在后面会用到。声明了一个数组。ArrayList的无参构造方法,将前面声明创建的大小为0的数组赋给elementData数组。这是ArrayList的有参构造方法,传入一个int类型的变量,相当于我们在使用arrayList的时候指定list的大小

    2022年8月8日
  • vuecli安装_vuecli搭建流程

    vuecli安装_vuecli搭建流程前言vue-cli是和vue进行深度组合的工具,可以快速帮我们创建vue项目,并且把一些脚手架相关的代码给我们创建好。真正使用vue开发项目,都是用vue-cli来创建项目的。vue-cli介绍

    2022年7月30日
  • c花体复制_花式字体大全可复制 花式字体转换器「建议收藏」

    c花体复制_花式字体大全可复制 花式字体转换器「建议收藏」求可复制花体字?1、windows系统的字体文件都放在这个文件夹下:C:\WINDOWS\Fonts,首先打开此文件夹。2、虽然在此文件夹下右键单击字体文件的菜单中无复制粘贴功能,但是却能使用“复制”快捷键,导出字体文件的方法也就是选中所要导出的字体文件,“Ctrl”“C”(复制快捷键),然后再粘贴到目标文件夹就好了。有好心人发一下英文字母h的花式字体吗,谢谢了,要可以复制的,小写的?这与字体有…

    2022年4月29日
  • DDL和DML的含义与区别「建议收藏」

    1、DDL和DML的含义1、DML(DataManipulationLanguage)数据操作语言-数据库的基本操作,SQL中处理数据等操作统称为数据操纵语言,简而言之就是实现了基本的“增删改查”操作。包括的关键字有:select、update、delete、insert、merge2、DDL(DataDefinitionLanguage)数据定义语言-用于定义和管理SQL数据库中的所有对象的语言,对数据库中的某些对象(例如,database,table)进行管理。包括的关键字有:crea

    2022年4月17日
  • Linux:常用命令大全

    Linux:常用命令大全

    2021年9月26日
  • mysql 启动/停止命令[通俗易懂]

    mysql 启动/停止命令[通俗易懂]mysql启动/停止命令

    2022年5月21日

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号