写来记录一下
网站:aHR0cHM6Ly95Z3AuZ2R6d2Z3Lmdvdi5jbi8jLzQ0MTkwMC9qeWdn
大概流程
测试反爬点
逆向分析
测试结果
测试反爬点
打开网页,我习惯先看Fetch/XHR,找找有无需要的数据接口,因为是学习的,直接就用items这个接口吧
打开数据包后可以看到,比较可疑的就这几个headers参数,看了下,很明显,X-Dgi-Req-Nonce参数猜测是随机的,X-Dgi-Req-Signature看着像是sha系列的,X-Dgi-Req-Timestamp时间戳,这不用猜了
逆向分析
因为这个请求是xhr的,可以使用xhr断点,但是我就直接堆栈了,直接点第一个,然后打上断点
然后就堆栈往下找,看到红框内的是不是好熟悉,手动狗头,这个就是用Promise对a数组内的函数进行调用,打上断点,因为a数组内比较少函数,所以就直接找加密的函数
很幸运,第一个就是,加密的函数,可以看到所有可疑参数都在了
接下来就简单啦,先研究一下他的逻辑,然后想扣就扣了,c值是固定的, 看l值,就是Aq(16)方法返回的
进去看看,其实就是取16位算过后的随机数再对ky字符串取值
再看d值,根据请求方式分为了两种,因为这个请求是post,而且get的比较简单,所以直接看其他的
f对象的p值其实就是data传入的值用&连接
再进Ig方法看看是咋加密的,可以看到就f对象的值拼接起来入参加密的,其中要注意的是data值需要根据键排序
到了这步,先测试一下刚刚的猜想,用这段字符串去加密试试看,明显就是原生的sha256加密,参数就是两个随机数再加上data的值
接下来也不想看了,就这样吧
测试结果
测试的时候遇到个问题,就是js的bool值否为false,python的为False,参数加密的时候需要转换一下
代码:
import random
import time
import hashlib
import requests
import json
ky = "zxcvbnmlkjhgfdsaqwertyuiop0987654321QWERTYUIOPLKJHGFDSAZXCVBNM"
Fq = ky + "-@#$%^&*+!"
def get_nonce(num):
nonce = ""
for i in range(num):
yq = int(random.random() * 62)
nonce += ky[yq]
return nonce
def get_signature(params_data: dict, _nonce: str, _timestamp: int):
c = 'k8tUyS$m'
p_data = dict(sorted(params_data.items(), key=lambda k: k[0]))
p_list = []
for key, value in p_data.items():
if str(value) == "False":
value = "false"
p_list.append(f"{key}={value}")
p_str = "&".join(p_list)
enc_str = _nonce + c + p_str + str(_timestamp)
_sha256 = hashlib.sha256()
_sha256.update(enc_str.encode("utf-8"))
return _sha256.hexdigest()
def get_data():
headers = {
"Accept": "application/json, text/plain, */*",
"Accept-Language": "zh-CN,zh;q=0.9,en-GB;q=0.8,en-US;q=0.7,en;q=0.6",
"Cache-Control": "no-cache",
"Connection": "keep-alive",
"Content-Type": "application/json",
"Pragma": "no-cache",
"Sec-Fetch-Dest": "empty",
"Sec-Fetch-Mode": "cors",
"Sec-Fetch-Site": "same-origin",
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/109.0.0.0 Safari/537.36",
"X-Dgi-Req-App": "ggzy-portal",
"X-Dgi-Req-Nonce": "2u6Imf7dpWhlIvoz",
"X-Dgi-Req-Signature": "9e1aba743fdda4ceb9091ae530442fa8e6dc465c01e966690c203cac8d114cc8",
"X-Dgi-Req-Timestamp": "1677152802087",
"sec-ch-ua": "\"Not_A Brand\";v=\"99\", \"Google Chrome\";v=\"109\", \"Chromium\";v=\"109\"",
"sec-ch-ua-mobile": "?0",
"sec-ch-ua-platform": "\"Windows\""
}
cookies = {
"_horizon_sid": "c15c53a7-b7b3-445a-8a45-af8d72057d17",
"_horizon_uid": "061cbea2-092d-4002-90d8-88848c7ac7e3"
}
url = "https:///脱敏处理/search/v1/items"
data = {
"type": "trading-type",
"publishStartTime": "",
"publishEndTime": "",
"siteCode": "441900",
"secondType": "A",
"projectType": "",
"thirdType": "",
"dateType": "",
"total": 0,
"pageNo": 1,
"pageSize": 10,
"openConvert": False
}
nonce = get_nonce(16)
timestamp = int(time.time() * 1000)
headers["X-Dgi-Req-Timestamp"] = str(timestamp)
headers["X-Dgi-Req-Nonce"] = nonce
headers["X-Dgi-Req-Signature"] = get_signature(params_data=data, _nonce=nonce, _timestamp=timestamp)
data = json.dumps(data, separators=(',', ':'))
response = requests.post(url, headers=headers, cookies=cookies, data=data)
print(response.text)
if __name__ == '__main__':
get_data()