python之js逆向爬虫实战(对加密的结果数据解密)
发表于:2024-07-17 23:11:48浏览:270次
引言
我们在爬取数据的时候经常遇到接口返回的数据是加密的,本文将演示如何对加密结果进行解密
环境
技术点:execjs
模块:execjs
# 安装execjs模块(需梯子)
pip install PyExecJS
适合AES解密/适合接口返回的加密数据
演示站点:https://www.bidcenter.com.cn/
演示接口:https://interface.bidcenter.com.cn/search/GetRelatedDataHandler.ashx
示例:
思路
- 找出解密的JS方法,具体方法参考:https://blog.dazijie.com/article/156
- 把该JS方法复制到本地JS文件,以便python方法调用(注意:若是该方法调用第三方JS模块,则我们本地也需要安装对应的模块才能调用起来)
实现
找到解密的JS方法
复制该方法放到本地的js文件,并安装所需的JS模块
- 找出解密方法的固定变量,KEY,IV等(方法中:variate.key,variate.aceIV)
- 完整JS代码
/**
* 引入模块并赋值给变量
*/
const CryptoJS = require("crypto-js")
const KEY = {
"words": [
863652730,
2036741733,
1164342596,
1782662963
],
"sigBytes": 16
}
const IV = {
"words": [
1719227713,
1314533489,
1397643880,
1749959510
],
"sigBytes": 16
}
/**
* AES解密
* @param {*} str 加密的字符串
* 这里调用了第三方库“CryptoJS”,安装模块命令:
* npm install crypto-js
* @returns
*/
function AESDecrypt(str) {
var nContent = CryptoJS.AES.decrypt(str, KEY, {
iv: IV,
mode: CryptoJS.mode.CBC,
padding: CryptoJS.pad.ZeroPadding
})
if (nContent && nContent != null) {
try {
var constr = CryptoJS.enc.Utf8.stringify(nContent)
if (constr != "") {
var data = JSON.parse(constr);
return data['other2']['listData'];
}
else
return null;
}
catch (err) {
return null;
}
} else {
return null;
}
}
- 使用
https://curlconverter.com/
快速生成请求方法,完整代码
这里有个坑,在引入execjs
前,必须先引入,否则会报错,估计是版本问题
import subprocess
from functools import partial
subprocess.Popen = partial(subprocess.Popen, encoding='utf-8')
- main.py
import requests
import subprocess
from functools import partial
subprocess.Popen = partial(subprocess.Popen, encoding='utf-8')
import execjs
class Spider:
"""
采集bidcenter
"""
def __init__(self) -> None:
self.max_page = 1
self.page_url = "https://www.bidcenter.com.cn/"
self.api_url = "https://interface.bidcenter.com.cn/"
self.limit = 10
pass
def start(self):
"""
入口
"""
headers = {
'accept': 'text/plain, */*; q=0.01',
'accept-language': 'zh-CN,zh;q=0.9',
'content-type': 'application/x-www-form-urlencoded; charset=UTF-8',
'origin': 'https://search.bidcenter.com.cn',
'priority': 'u=1, i',
'referer': 'https://search.bidcenter.com.cn/',
'sec-ch-ua': '"Not/A)Brand";v="8", "Chromium";v="126", "Google Chrome";v="126"',
'sec-ch-ua-mobile': '?0',
'sec-ch-ua-platform': '"Windows"',
'sec-fetch-dest': 'empty',
'sec-fetch-mode': 'cors',
'sec-fetch-site': 'same-site',
'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36',
}
# keywords = input("请输入关键字:")
keywords = "服务器"
for x in range(self.max_page):
data = {
'from': '6137',
'guid': 'd124a51f-275f-407c-8448-0f6868899ad6',
'location': '6138',
'token': '',
'next_token': '',
'keywords': keywords,
'mod': '0',
'page': str(x+1),
}
response = requests.post(f'{self.api_url}search/GetSearchProHandler.ashx', headers=headers, data=data)
if response.status_code == 200:
mylist = self.mydecrypt(response.text)
print(mylist)
else:
print("请求失败")
pass
def mydecrypt(self,encrypt_data):
"""
执行JS文件
"""
with open("./my.js","r",encoding="utf-8") as f:
# js_code 就是my.js中的代码
js_code = f.read()
# 把 js_code 转成能在python中执行的代码
ctx = execjs.compile(js_code)
# 调用AESDecrypt方法,并传入参数encrypt_data
return ctx.call("AESDecrypt",encrypt_data)
if __name__ == "__main__":
spider = Spider()
spider.start()
栏目分类全部>