在学习爬虫的过程中,我们会遇见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)