在学习爬虫的过程中,我们会遇见AES等等加密问题,我们需要在js端找到未加密对的数据,在python端对data数据进行加密,这边我们就需要用到Crypto模块,但是网上目前下载该模块还是比较麻烦的。

我们观察官方文档发现:This software is no longer maintained. | PyCrypto

 很可惜,上面写者This software is no longer maintained.该模块已经不再维护了

但是我们还是要用的。

之前的解决方法是下载pycrypto模块就可以使用了,这边我第一反应是下载crypto,结果发现没用,发现需要下载pycrypto。

pip install pycrypto -i http://mirrors.aliyun.com/pypi/simple/ --trusted-host mirrors.aliyun.com

pip install wheel -i http://mirrors.aliyun.com/pypi/simple/ --trusted-host mirrors.aliyun.com

pip install crypto -i http://mirrors.aliyun.com/pypi/simple/ --trusted-host mirrors.aliyun.com

但是下载过程中一直报错无法下载。于是放弃这条路,但是还是建议先把crypto下载下来包括AES
正确快捷解决方法,(已解决问题)

目前是出现pycryptodome模块可以替代,其还在之前的crypto模块中,这边我们只需要在pycharm中,在你需要使用程序下,在Terminal中下载这两个模块
 

1.pycryptodome安装
pip install pycryptodome -i http://mirrors.aliyun.com/pypi/simple/ --trusted-host mirrors.aliyun.com
2.pycryptodomex安装

pip install pycryptodomex -i http://mirrors.aliyun.com/pypi/simple/ --trusted-host mirrors.aliyun.com

然后找到python编译器的安装位置

 将原本的该文件的名字改为大写的Crypto,之前是小写crypto

这样就可以解决了

这边展示一下抓取网易云歌曲的评论,这边就采用了AES加密歌曲《牡丹江》

import requests
#pip install pycrypto
#这里需要安装 pip install pycryptodome -i http://mirrors.aliyun.com/pypi/simple/ --trusted-host mirrors.aliyun.com
from base64 import b64encode
import json
from Crypto.Cipher import AES
if __name__=='__main__':
    #1.找到未加密的参数
    #var bKB5G = window.asrsea(JSON.stringify(i2x), buV2x(["流泪", "强"]), buV2x(Rg8Y.md), buV2x(["爱心", "女孩", "惊恐", "大笑"]));加密语法
    #2.想办法把参数进行加密(必须参考网易的逻辑)param ->encText ,encSecKey->encSecKey
    #3.请求到网易,拿到评论信息
    url='https://music.163.com/weapi/comment/resource/comments/get?csrf_token='
    #请求方式是POST
    headers = {
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/104.0.0.0 Safari/537.36'
    }
    data={
        'csrf_token': "",
        'cursor': "-1",
        'offset': "0",
        'orderType': "1",
        'pageNo': "1",
        'pageSize': "20",
        'rid': "R_SO_4_368794",
        'threadId': "R_SO_4_368794"
    }
    # "rid=R_SO_4_368794&threadId=R_SO_4_368794&pageNo=1&pageSize=20&cursor=-1&offset=0&orderType=1"
    print(json.dumps(data))
    e = "010001"
    f = "00e0b509f6259df8642dbc35662901477df22677ec152b5ff68ace615bb7b725152b3ab17a876aea8a5aa76d2e417629ec4ee341f56135fccf695280104e0312ecbda92557c93870114af6c9d05c4f7f0c3685b7a46bee255932575cce10b424d813cfe4875d3e82047b97ddef52741d546b8e289dc6935b3ece0462db0a22b8e7"
    g = "0CoJUm6Qyw8W8jud"
    i = "WsXy0BKCyb9uStPE"


    # 定死i 以拿到以定死的i的encSecKey 不然它变化
    def get_encSecKey():
        # return "091870ee1d9eaa44f50d8788f77f9c625cafc76c4ade76499875831f8b3ded2f417e4909cb47d8c97bfe5e9eab0466b265e1ad2d96beb0a392f3c54394171f9caba249b01c76630b4c98a63f17236ee783c370a7ff48a6cc7417972afe09a0811027f61bd5c9179deb7174d215e6c3896dc33792d79540b835721ab3e0a95ab0"
        return "2331db0c4f71b25b3ff19e347294e2a75b4bd3b1d7a991f7b9d7feeec08f8cdbd1e653e3205fe7867a2171d2c373113b4aa3920a34afef505cc3f912543cefdc65f13deace2db212ea3353f84d503ceb5a1f4c0474749eb712b2d20760d9b1b3a3b4e57d6787e3e254ddb53dd6fe6734aad97f518a81bb20d1b205c95fca3b2a"

    def get_params(data):  # 默认收到的是字符串,并非字典

        first = enc_params(data, g)
        second = enc_params(first, i)
        return second
    #转化成16倍数
    def to_16(data):
        pad = 16 - len(data) % 16
        # print("pad: %d , data : %s" %(pad,data))
        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) #创造加密器
        bs0=aes.encrypt(data.encode("utf-8")) #加密,加密对的内容的长度必须是16的倍数

        return str(b64encode(bs0), "utf-8")




    #处理加密过程
    '''
    function a(a) { #返回随机的16位字符串
        var d, e, b = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789", c = "";
        for (d = 0; a > d; d += 1) #循环16次
            e = Math.random() * b.length, #随机数
            e = Math.floor(e), #取整
            c += b.charAt(e); #取字符串的某某位置
        return c
    }
    function b(a, b) {  #a时要加密的内容
        var c = CryptoJS.enc.Utf8.parse(b) #b是密钥
          , d = CryptoJS.enc.Utf8.parse("0102030405060708")
          , e = CryptoJS.enc.Utf8.parse(a) #e是数据
          , f = CryptoJS.AES.encrypt(e, c, { #AES加密 c是加密的密钥
            iv: d,  #偏移量
            mode: CryptoJS.mode.CBC # 模式采用CBC
        });
        return f.toString()
    }
    g="0CoJUm6Qyw8W8jud"
    e="010001"
    f="00e0b509f6259df8642dbc35662901477df22677ec152b5ff68ace615bb7b725152b3ab17a876aea8a5aa76d2e417629ec4ee341f56135fccf695280104e0312ecbda92557c93870114af6c9d05c4f7f0c3685b7a46bee255932575cce10b424d813cfe4875d3e82047b97ddef52741d546b8e289dc6935b3ece0462db0a22b8e7"
    function c(a, b, c) { #c不产生随机数
        var d, e;
        return setMaxDigits(131),
        d = new RSAKeyPair(b,"",c),
        e = encryptedString(d, a)
    }
    function d(d, e, f, g) { d:数据 e:buV2x(["流泪", "强"]) ==010001 f: buV2x(Rg8Y.md)==f g = 0CoJUm6Qyw8W8jud
    
        var h = {} # 空对象
          , i = a(16); # i就是一个16位的随机值,把i设置成定值,得到的key是一个定值
        return h.encText = b(d, g), #g 是密钥
        h.encText = b(h.encText, i), #返回的就是params i也是密钥
        h.encSecKey = c(i, e, f), #得到的就是enSecKey ,e和f是定值
        h
    }
    function e(a, b, d, e) {
        var f = {};
        return f.encText = c(a + e, b, d),
        f
    }
    两次加密:
    数据+g =>b => 第一次加密 +i => b =params
    '''
    resp = requests.post(url, data={
        "params": get_params(json.dumps(data)),
        "encSecKey": get_encSecKey()
    })
    print(resp.status_code)
    print(resp.text)

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐