python+execjs爬取网易云评论

python+execjs爬取网易云评论

分析网站

首先打开网易云首页,随便点一首歌曲进入到评论区。
在这里插入图片描述
接着按F12进入开发者工具,重新刷新页面找发送评论数据的接口,找到接口链接为:[https://music.163.com/weapi/v1/resource/comments/A_PL_0_924680166?csrf_token=]
在接口返回的数据里有个键为comments里面就包含了页面上的评论,好了,接下来看接口需要发送什么数据给后台,有两个参数分别为params和encSecKey,这两个参数都经过了加密,所以我们要找到参数对应的js文件,按ctrl+shift+F搜索encSecKey,发现对应着core开头的js文件,接下来就直接进入此文件分析js。
在这里插入图片描述在这里插入图片描述

JS分析

在这里插入图片描述
进入到此页面后我们就来开始分析js代码,首先按ctrl+f查找encSecKey,发现paramsencSecKey的返回值都在13020行代码那里,从图中看出paramsencSecKey都是接收于bXL9C这个值里的属性的,这时我们就要开始分析13017行这行代码的意思了,我们首先可以打上断点,然后重新刷新看下window.asrsea这个方法里的四个参数分别是什么。在这里插入图片描述
在这里插入图片描述
接下来我们就可以来记下4个参数,分别分为(a,b,c,d)
a = “{“rid”:“A_PL_0_924680166”,“offset”:“0”,“total”:“true”,“limit”:“20”,“csrf_token”:”"}"
b = “010001”
c = “00e0b509f6259df8642dbc35662901477df22677ec152b5ff68ace615bb7b725152b3ab17a876aea8a5aa76d2e417629ec4ee341f56135fccf695280104e0312ecbda92557c93870114af6c9d05c4f7f0c3685b7a46bee255932575cce10b424d813cfe4875d3e82047b97ddef52741d546b8e289dc6935b3ece0462db0a22b8e7”
d = “0CoJUm6Qyw8W8jud”
经过几次测试发现除了a会改变之外,其余三个值都是固定值。
再进一步查找window.asrsea究竟是什么。

在这里插入图片描述发现window.asrsea对应着d方法,此时我们发现d方法返回值对应着我们前面的两个参数,好了,到这就知道了方法源头,因为d方法里面调用的b、c方法这些都是加密的,所以我们可以利用execjs来破解,而不需要自己去用python重写js加密代码了。

execjs解密js

此时我们可以把js代码复制到pycharm中分析,我们需要的方法分别是js代码中的a、b、c、d四个方法,我们可以将其复制到新的js文件中。
复制前:
在这里插入图片描述复制后:
在这里插入图片描述然后在python代码中我们可以用execjs来调用js代码,并把之前记录的四个参数传参进去给d方法,代码如下:在这里插入图片描述
此时会发现有报错,会提醒未定义CryptoJS,这时我们就需要到npm中安装了,全局安装cnpm install crypto-js --save-dev,并到js文件中引入此代码let CryptoJS = require(‘crypto-js’);,再到py文件中的修改此处,添加cwd指定你的npm路径,如果不知道你的npm路径是什么,可以在cmd中输入npm config get prefix获取。
此时还会发现报错缺少函数什么的,也就是js代码中的一些函数,这时我们从js代码中的12447行的RSAKeyPair()方法开始复制到12869此处全部复制到js文件中,基本上运行就可以获取两个加密参数的值了。在这里插入图片描述

运行结果

在这里插入图片描述
两个参数和获取的评论。

代码

python

import requests
import execjs
import json

def main(number):
    '''
    :param number: 歌曲的id
    :return:
    '''
    node = execjs.get()
    file = './demo.js'
    ctx = node.compile(open(file).read(), cwd='C:\\Users\\Administrator\\AppData\\Roaming\\npm') # 读取文件
    num = 0 # 计数
    while True:
        a = {
   "rid": "A_PL_0_%s" % number, "offset": "%s" % num, "total": "true", "limit": "20", "csrf_token": ""}
        b = "010001"
        c = "00e0b509f6259df8642dbc35662901477df22677ec152b5ff68ace615bb7b725152b3ab17a876aea8a5aa76d2e417629ec4ee341f56135fccf695280104e0312ecbda92557c93870114af6c9d05c4f7f0c3685b7a46bee255932575cce10b424d813cfe4875d3e82047b97ddef52741d546b8e289dc6935b3ece0462db0a22b8e7"
        d = "0CoJUm6Qyw8W8jud"
        result = ctx.eval('d("%s","%s","%s","%s")' % (a, b, c, d)) # 调用d方法
        params = result['encText'] # 获取encText
        encSecKey = result['encSecKey'] # 获取encSecKey
        print(params)
        print(encSecKey)
        url = "https://music.163.com/weapi/v1/resource/comments/A_PL_0_%s" % number
        headers = {
   
            "Referer": 'https://music.163.com/',
            "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Safari/537.36"
            }
        formdata = {
   'params': params, 'encSecKey': encSecKey}
        resp = requests.post(url, headers=headers, data=formdata)
        resp = json.loads(resp.text)['comments']
        if len(resp) <= 0:
            break
        for comments in resp:
            print(comments['content'])
        num += 20

if __name__ == '__main__':
    main(308240095)

js代码:

let CryptoJS = require('crypto-js');
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) {
    // 1 4
    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), // 1 4
    h.encText = b(h.encText, i),
    h.encSecKey = c(i, e, f), // 2 3
    h
}

function RSAKeyPair(a, b, c) {
   
    this.e = biFromHex(a),
    this.d = biFromHex(b),
    this.m = biFromHex(c),
    this.chunkSize = 2 * biHighIndex(this.m),
    this.radix = 16,
    this.barrett = new BarrettMu(this.m)
}
function twoDigit(a) {
   
    return (10 > a ? "0" : "") + String(a)
}
function encryptedString(a, b) {
   
    for (var f, g, h, i, j, k, l, c = new Array, d = b.length, e = 0; d > e; )
        c[e] = b.charCodeAt(e),
        e++;
    for (; 0 != c.length % a.chunkSize; )
        c[e++] = 0;
    for (f = c.length,
    g = "",
    e = 0; f > e; e += a.chunkSize) {
   
        for (j = new BigInt,
        h = 0,
        i = e; i < e + a.chunkSize; ++h)
            j.digits[h] = c[i++],
            j.digits[h] += c[i++] << 8;
        k = a.barrett.powMod(j, a.e),
        l = 16 == a.radix ? biToHex(k) : biToString(k, a.radix),
        g += l + " "
    }
    return g.substring(0, g.length - 1)
}
function decryptedString(a, b) {
   
    var e, f, g, h, c = b.split(" "), d = "";
    for (e = 0; e < c.length; ++e)
        for (h =
  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值