python爬虫(6)-网易云评论

# -*- coding: utf-8 -*-
"""
@Time    :  2022/3/22 10:33
@Author  : Andrew
@File    : 网易云评论.py
"""
# 找到未加密的参数
# 想办法把参数加密。过程必须参考网易加密过程 params,encSeckey
# 请求网易拿到评论解析 POST
# from Crypto.cipher import AES
import json
from base64 import b64encode

import requests
from Crypto.Cipher import AES

url = "https://music.163.com/weapi/comment/resource/comments/get"

# 1.首先在源代码里是没有找到评论的,单纯的请求当前页面源代码无法拿到数据
# 2.通过刷新当前页面,f12抓包,找到了评论是在一个叫get?scf_token=的请求,通过预览发现了评论,
# 3.查看其header请求的是上面这个url   https://music.163.com/weapi/comment/resource/comments/get,后面的csf_token需要登陆后才有值,这里可以不考虑
# 4.鼠标往下滑 发现了两个参数,params,encSeckey但是被加密的,现在就要考虑解密了
# 5.在edge浏览器中,有一个发起程序,点进去会发现一堆 调用 自下而上的排列
# 6.点击第一个调用,会发现大量的代码,点击左下角的{},可以让代码格式化,此时鼠标点会移动到一个地方,注意鼠标光点所在的函数的返回值参数
# 7.在此处加上断点,刷新当前页面,查看作用域中 返回值参数 里面url是否和上面的一样
# 8.如果不一样,点击上面的暂停按钮(因为加了断点,程序并没有运行完),让程序继续执行,直到找到和上面一样的url
# 9.这个时候,查看调用堆栈,里面依旧是一堆调用,然后往下依次点击,每点击一个调用,就点击一个{},找到鼠标光点所在函数的返回值参数,
# 10.对照查看作用域该参数里面params,encSeckey值,
# 11.什么时候被加密,假如在第四行返回值参数我们能认识的值(类似key=value),但是在第三行就变成了不认识的值(就是第四步发现的样子,params=无规则字符串),那么就是在第三行被加密了
# 12.在该函数(见QQ截图)的第一行代码处设置断点,关掉之前的断点,点击那个暂停按钮把当前跑完,
# 13.当显示为“||”时,重新刷新页面,点击播放键样子的按钮,让程序执行,找url末尾是get的,找到后,点击执行按钮旁边的下一步,并查看作用域的data
# 14.发现加密过程 window.arsea(参数,XXX,XXX,XX),而params:encText,encSecKey:encSecKey
# 15.data是i4m,也就是网易解密后的参数,请求方式:POST
# 16.把window.arsea里面的参数一一拿出来,有些就放在console运行一下发现是定值
# 17.给d的函数里加断点,然后找到i的值,让他固定,因为它本来就是一个随机数
data = {
    "csrf_token": "",
    "cursor": "-1",
    "offset": "0",
    "orderType": "1",
    "pageNo": "1",
    "pageSize": "20",
    "rid": "R_SO_4_1927142874",
    "threadId": "R_SO_4_1927142874"
}
# 处理加密过程

"""
 function 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 # 16个随机字符串
    }
    function b(a, b) {         #a是要加密的
        var c = CryptoJS.enc.Utf8.parse(b)    #c 加密密钥,b就是密钥
          , d = CryptoJS.enc.Utf8.parse("0102030405060708")
          , e = CryptoJS.enc.Utf8.parse(a)    #e是数据
          , 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) {d:数据data,
        var h = {}
          , i = a(16); #16个随机值
        h.encText = b(d, g), #g是密钥
        h.encText = b(h.encText, i), #这个地方就是params
        h.encSecKey = c(i, e, f), ##这个地方就是encSeckey  i也是密钥,这个时候把i固定,e固定、f固定、那么encSecKey也是固定的
        return h
    }
"""
e = '010001'
f = '00e0b509f6259df8642dbc35662901477df22677ec152b5ff68ace615bb7b725152b3ab17a876aea8a5aa76d2e417629ec4ee341f56135fccf695280104e0312ecbda92557c93870114af6c9d05c4f7f0c3685b7a46bee255932575cce10b424d813cfe4875d3e82047b97ddef52741d546b8e289dc6935b3ece0462db0a22b8e7 '
g = '0CoJUm6Qyw8W8jud'
i = "eMgnsUBjn5vbYOEQ"


# h.encSecKey = c(i, e, f),  ##这个地方就是encSeckey  i也是密钥,这个时候把i固定,e固定、f固定、那么encSecKey也是固定的
def get_encSeckey():
    return "948a56412ac45bceb6ca1b8148716597a55efb841d7457fed4059552a1123c18dd193a7ef4e9d04163f59d34e9c665a88dba31ed808c2c8a5cd9c27fe0eced56e1efd94d9a3ca3696c7bbef5081e0272368c465c40f1c0903f1cb99d70089ab85c30f7b1b9fd7b459559781b172ec3dafe75e03b3a3194858027f3126b0b7ed5 "


# h.enctext经历了两次加密
#     还原d,默认收到的data是字符串
def get_params(data):
    first = enc_parms(data, g)
    second = enc_parms(first, i)
    return second  # params


def enc_parms(data, key):
    # 还原b加密过程
    data = to_16(data)
    aes = AES.new(key=key.encode("utf-8"), IV="0102030405060708".encode("utf-8"), mode=AES.MODE_CBC)
    bs = aes.encrypt(data.encode("utf-8"))  # 加密要求,加密内容的长度必须是16的倍数
    return str(b64encode(bs), "utf-8")

# 处理ValueError: Data must be padded to 16 byte boundary in CBC mode
def to_16(data):
    pad = 16 - len(data) % 16
    data += chr(pad) * pad
    return data


resp = requests.post(url, data={
    "params": get_params(json.dumps(data)),
    "encSecKey": get_encSeckey()
})
print(resp.text)
resp.close()

 

 

 

 

posted @ 2022-03-22 13:43  乔十六  阅读(176)  评论(1编辑  收藏  举报