[Python] 纯文本查看 复制代码
import hmac
import hashlib
import base64
import urllib.parse
import requests
import execjs
import json
import zlib
from hashlib import md5
from datetime import datetime, timezone
from Crypto.Util.Padding import pad
from Crypto.Cipher import AES
from binascii import b2a_hex, a2b_hex
import cv2
import numpy as np
proxies = {
'http': None,
'https': None
}
# proxies = {
# 'http': 'http://127.0.0.1:8888',
# 'https': 'http://127.0.0.1:8888'
# }
# 环境
def env_init(config):
return [
"W.10030",
"1.5",
"11",
"Xiaomi",
"Blink",
"Win32",
"WeChat",
"8.0.45.2521",
"0",
"[]",
"false",
"1",
"Google Inc. (AMD)",
"ANGLE (AMD, AMD Radeon R5 430 (0x00006611) Direct3D11 vs_5_0 ps_5_0, D3D11)",
"false",
"false",
"0",
"0",
"0",
"3b6dc923ad5dae469c99a6242c439c3d",
"63",
"",
"8",
"0*0*0*0",
"24",
"24",
"srgb",
"false",
"false",
"false",
"0",
"0",
"d57f20fcf75a171f408d067e1f72f952",
"",
"8",
"[[audiooutput,]]",
"Android",
"11",
"1",
"true",
"zh-CN",
"Asia/Shanghai",
"101.17.217.107",
"",
"true",
"true",
"true",
"700*400",
"true",
"1",
"true",
"true",
"",
"https://app.appykt.com/",
"",
"700*400",
"700*400",
"700*400",
"0",
"700*400",
"false",
"",
"false",
"92.0.4515.131",
" Mozilla/5.0 (Linux; Android 11; M2002J9E Build/RKQ1.200826.002; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/92.0.4515.131 Mobile Safari/537.36 MMWEBID/4339 MicroMessenger/8.0.45.2521(0x28002D3D) WeChat/arm64 Weixin NetType/WIFI Language/zh_CN ABI/arm64",
"unspecified",
"false",
"saf-captcha",
"",
"[]",
"-480",
"3HTz8ltU3tew85f2Yh9SaNffDOC7XPjXDlHoZ1SS",
"1723797627422",
"TbRBea0TsuVF19EBJT9hvm8mA89aNKXvPOPGh8qmkp",
"",
"mobile",
"",
"",
"9d4568c009d203ab10e33ea9953a0264",
"99914b932bd37a50b983c5e7c90ae93b",
"5.0 (Linux; Android 11; M2002J9E Build/RKQ1.200826.002; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/92.0.4515.131 Mobile Safari/537.36 MMWEBID/4339 MicroMessenger/8.0.45.2521(0x28002D3D) WeChat/arm64 Weixin NetType/WIFI Language/zh_CN ABI/arm64",
"Mozilla",
"64",
"",
"",
"0",
"0",
config['timestamp'],
"MSMwIzAjMCMwIzAjMCMwIzAjMCMwIzAjMCMwIzAjMCMwIzA=",
"1",
"1",
"true",
"1",
"1",
"1",
"1",
"1",
"1",
"1",
"1",
"1",
"1",
"1",
"1",
"1",
"1",
"1",
"1",
"0",
"0",
"[]",
"0|0|0|0|0|0|1|1|0|1|2|1|1|2|1|1|1|0|1|1|0|1|1|0|1|2|1|1|1|0|1|1|0",
"0"
]
def get_uuid():
js_code = """
function SignatureNonce() {
var t, r, n = "";
for (t = 0; t < 32; t++)
r = 16 * Math.random() | 0,
8 !== t && 12 !== t && 16 !== t && 20 !== t || (n += "-"),
n += (12 === t ? 4 : 16 === t ? 3 & r | 8 : r).toString(16);
return n
}
"""
ctx = execjs.compile(js_code)
return ctx.call('SignatureNonce')
# ISO 8601格式,'Z'表示UTC时区
def get_time():
now = datetime.now(timezone.utc)
# 格式化日期时间为ISO 8601格式,'Z'表示UTC时区
iso_time = now.strftime('%Y-%m-%dT%H:%M:%S') + 'Z'
return iso_time
# 获取随机字符串
def get_rondom(number):
js_code = """
function St(n) {
for (var t = "", r = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ", e = arguments.length > 1 && void 0 !== arguments[1] && arguments[1] ? An()(r).call(r, 10) : r, u = 0; u < n; u++)
t += e.charAt(Math.floor(Math.random() * e.length));
return t
}
"""
ctx = execjs.compile(js_code)
return ctx.call('St', number)
# 初始获取滑块和config
def init_captcha():
url = "https://fr0j29.captcha-open.aliyuncs.com/"
headers = {
"Host": "fr0j29.captcha-open.aliyuncs.com",
"Connection": "keep-alive",
"Content-Length": "477",
"Pragma": "no-cache",
"Cache-Control": "no-cache",
"Content-Type": "application/x-www-form-urlencoded; charset=UTF-8",
"User-Agent": "Mozilla/5.0 (Linux; Android 11; M2002J9E Build/RKQ1.200826.002; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/92.0.4515.131 Mobile Safari/537.36 MMWEBID/4339 MicroMessenger/8.0.45.2521(0x28002D3D) WeChat/arm64 Weixin NetType/WIFI Language/zh_CN ABI/arm64",
"Accept": "*/*",
"Origin": "https://app.appykt.com",
"Referer": "https://app.appykt.com/",
"Accept-Language": "zh-CN,zh;q=0.9"
}
time_stamp = get_time()
sign_nonce = get_uuid()
param = {'AccessKeyId': 'LTAI5tSEBwYMwVKAQGpxmvTd',
'Action': 'InitCaptcha',
'DeviceData': 'byAgDBTTWK6iQ63aLnMRvywYbJ50c453wUz9CdNf4pWB+H4EOu7koqzwbASi1Zy3OrPsdmv/kr4CT4skoBPotjJal86WIOATPokFTSANe8P8K8sPwx4Mk/bEd33ZmVPdV8YDQbT3U+RDhgTfZC0pYQ==',
'Format': 'JSON',
'Language': 'cn',
'Mode': 'popup',
'SceneId': 'fdh8368b',
'SignatureMethod': 'HMAC-SHA1',
'SignatureNonce': sign_nonce,
'SignatureVersion': '1.0',
'Timestamp': time_stamp,
'Version': '2023-03-05'
}
param_to_str = urllib.parse.urlencode(param)
sign_str = f'POST&%2F&{urllib.parse.quote(param_to_str)}'
sign_true = hmac_sha1(sign_str, 'YSKfst7GaVkXwZYvVihJsKF9r89koz&')
payload = param_to_str + '&Signature=' + urllib.parse.quote(sign_true)
try:
response = requests.request("POST", url, data=payload, headers=headers, proxies=proxies, verify=False)
return response.json()
except Exception as e:
return False
# 获取滑块
def get_captcha(token, certifyid):
url = "https://fr0j29.captcha-open.aliyuncs.com/"
headers = {
"Host": "fr0j29.captcha-open.aliyuncs.com",
"Connection": "keep-alive",
"Content-Length": "477",
"Pragma": "no-cache",
"Cache-Control": "no-cache",
"Content-Type": "application/x-www-form-urlencoded; charset=UTF-8",
"User-Agent": "Mozilla/5.0 (Linux; Android 11; M2002J9E Build/RKQ1.200826.002; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/92.0.4515.131 Mobile Safari/537.36 MMWEBID/4339 MicroMessenger/8.0.45.2521(0x28002D3D) WeChat/arm64 Weixin NetType/WIFI Language/zh_CN ABI/arm64",
"Accept": "*/*",
"Origin": "https://app.appykt.com",
"Referer": "https://app.appykt.com/",
"Accept-Language": "zh-CN,zh;q=0.9"
}
time_stamp = get_time()
sign_nonce = get_uuid()
param = {'AccessKeyId': 'LTAI5tSEBwYMwVKAQGpxmvTd',
'Action': 'InitCaptcha',
'CertifyId': certifyid,
'Format': 'JSON',
'Language': 'cn',
'DeviceToken': token,
'SceneId': 'fdh8368b',
'SignatureMethod': 'HMAC-SHA1',
'SignatureNonce': sign_nonce,
'SignatureVersion': '1.0',
'Timestamp': urllib.parse.quote(time_stamp),
'Version': '2023-03-05'
}
param_to_str = obj_sort_str(param)
sign_str = f'POST&%2F&{urllib.parse.quote(param_to_str)}'
sign_true = hmac_sha1(sign_str, 'YSKfst7GaVkXwZYvVihJsKF9r89koz&')
payload = param_to_str + '&Signature=' + urllib.parse.quote_plus(sign_true)
try:
response = requests.request("POST", url, data=payload, headers=headers, proxies=proxies, verify=False)
return response.json()
except Exception as e:
return False
# 轨迹
def get_track(time, x):
return {
"mousemove": [
{
"x": 89,
"y": 441,
"t": 265988
}, {
"x": 93,
"y": 440,
"t": 266014
}, {
"x": 93,
"y": 440,
"t": 266041
}, {
"x": 105,
"y": 438,
"t": 266067
}, {
"x": 105,
"y": 438,
"t": 266093
}, {
"x": 119,
"y": 436,
"t": 266123
}, {
"x": 119,
"y": 436,
"t": 266150
}, {
"x": 134,
"y": 434,
"t": 266180
}, {
"x": 134,
"y": 434,
"t": 266206
}, {
"x": 148,
"y": 433,
"t": 266235
}, {
"x": 153,
"y": 433,
"t": 266262
}, {
"x": 153,
"y": 433,
"t": 266288
}, {
"x": 166,
"y": 433,
"t": 266315
}, {
"x": 166,
"y": 433,
"t": 266340
}, {
"x": 184,
"y": 432,
"t": 266366
}, {
"x": 184,
"y": 432,
"t": 266392
}, {
"x": 189,
"y": 432,
"t": 266418
}, {
"x": 197,
"y": 431,
"t": 266449
}, {
"x": 219,
"y": 429,
"t": 266475
}, {
"x": 219,
"y": 429,
"t": 266501
}, {
"x": 233,
"y": 428,
"t": 266531
}, {
"x": 233,
"y": 428,
"t": 266557
}, {
"x": 252,
"y": 427,
"t": 266588
}, {
"x": 252,
"y": 427,
"t": 266613
}, {
"x": 263,
"y": 427,
"t": 266645
}, {
"x": 263,
"y": 427,
"t": 266672
}, {
"x": 270,
"y": 427,
"t": 266698
}, {
"x": 279,
"y": 427,
"t": 266732
}, {
"x": 285,
"y": 427,
"t": 266759
}, {
"x": 296,
"y": 427,
"t": 266787
}, {
"x": 296,
"y": 427,
"t": 266814
}, {
"x": 302,
"y": 427,
"t": 266846
}, {
"x": 309,
"y": 427,
"t": 266875
}, {
"x": 309,
"y": 427,
"t": 266901
}, {
"x": 314,
"y": 427,
"t": 266949
}, {
"x": 313,
"y": 427,
"t": 267227
}, {
"x": 313,
"y": 427,
"t": 267253
}
],
"mouseclick": [
{
"x": 220,
"y": 432,
"t": 132055
}, {
"x": 370,
"y": 436,
"t": 133213
}, {
"x": 155,
"y": 150,
"t": 135287
}, {
"x": 121,
"y": 497,
"t": 136189
}, {
"x": 136,
"y": 520,
"t": 136580
}, {
"x": 146,
"y": 535,
"t": 136998
}, {
"x": 146,
"y": 535,
"t": 137315
}, {
"x": 146,
"y": 535,
"t": 137515
}, {
"x": 146,
"y": 535,
"t": 137708
}, {
"x": 363,
"y": 664,
"t": 138501
}, {
"x": 304,
"y": 439,
"t": 140045
}, {
"x": 367,
"y": 663,
"t": 140851
}, {
"x": 239,
"y": 264,
"t": 141806
}, {
"x": 187,
"y": 304,
"t": 144349
}, {
"x": 146,
"y": 377,
"t": 148716
}, {
"x": 175,
"y": 430,
"t": 153711
}, {
"x": 347,
"y": 436,
"t": 154845
}, {
"x": 80,
"y": 441,
"t": 265834
}
],
"keyup": [
{
"t": 143194
}, {
"t": 143196
}, {
"t": 143402
}, {
"t": 143403
}, {
"t": 143818
}, {
"t": 143819
}, {
"t": 145570
}, {
"t": 145728
}, {
"t": 145932
}, {
"t": 146418
}, {
"t": 146586
}, {
"t": 146794
}, {
"t": 146996
}, {
"t": 147210
}, {
"t": 147396
}, {
"t": 147587
}, {
"t": 147787
}, {
"t": 150491
}, {
"t": 150701
}, {
"t": 151012
}, {
"t": 151266
}, {
"t": 151482
}, {
"t": 151682
}, {
"t": 151868
}, {
"t": 152068
}, {
"t": 152276
}, {
"t": 152475
}, {
"t": 152692
}
],
"scrollTop": [],
"scrollLeft": [],
"clientType": "mobile",
"startTime": 1724027006319,
"timestamp": time
}
# 提交设备 Log2
def device_log2(data):
url = "https://cloudauth-device.aliyuncs.com/"
headers = {
"Accept": "*/*",
"Accept-Language": "zh-CN,zh;q=0.9",
"Cache-Control": "no-cache",
"Connection": "keep-alive",
"Content-Type": "application/x-www-form-urlencoded; charset=UTF-8",
"Origin": "https://app.appykt.com",
"Pragma": "no-cache",
"Referer": "https://app.appykt.com/",
"Sec-Fetch-Dest": "empty",
"Sec-Fetch-Mode": "cors",
"Sec-Fetch-Site": "cross-site",
"User-Agent": "Mozilla/5.0 (iPhone; CPU iPhone OS 16_6 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.6 Mobile/15E148 Safari/604.1",
"sec-ch-ua-platform": "\"Windows\""
}
param = {
"AccessKeyId": "LTAI5tGjnK9uu9GbT9GQw72p",
"Version": "2020-10-15",
"SignatureMethod": "HMAC-SHA1",
"SignatureVersion": "1.0",
"Format": "JSON",
"Action": "Log2",
"Data": urllib.parse.quote_plus(data),
"SignatureNonce": get_uuid()
}
param_to_str = obj_sort_str(param)
sign_str = f'POST&%2F&{urllib.parse.quote(param_to_str)}'
sign_true = hmac_sha1(sign_str, 'fpOKzILEajkqgSpr9VvU98FwAgIRcX&')
payload = param_to_str + '&Signature=' + urllib.parse.quote_plus(sign_true)
response = requests.post(url, headers=headers, data=payload, proxies=proxies, verify=False)
print(response)
print(response.text)
# 设备+轨迹 Log3
def device_log3(data):
url = "https://cloudauth-device.aliyuncs.com/"
headers = {
"Accept": "*/*",
"Accept-Language": "zh-CN,zh;q=0.9",
"Cache-Control": "no-cache",
"Connection": "keep-alive",
"Content-Type": "application/x-www-form-urlencoded; charset=UTF-8",
"Origin": "https://app.appykt.com",
"Pragma": "no-cache",
"Referer": "https://app.appykt.com/",
"Sec-Fetch-Dest": "empty",
"Sec-Fetch-Mode": "cors",
"Sec-Fetch-Site": "cross-site",
"User-Agent": "Mozilla/5.0 (iPhone; CPU iPhone OS 16_6 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.6 Mobile/15E148 Safari/604.1",
"sec-ch-ua-platform": "\"Windows\""
}
param = {
"AccessKeyId": "LTAI5tGjnK9uu9GbT9GQw72p",
"Version": "2020-10-15",
"SignatureMethod": "HMAC-SHA1",
"SignatureVersion": "1.0",
"Format": "JSON",
"Action": "Log3",
"Data": urllib.parse.quote_plus(data),
"SignatureNonce": get_uuid()
}
param_to_str = obj_sort_str(param)
sign_str = f'POST&%2F&{urllib.parse.quote(param_to_str)}'
sign_true = hmac_sha1(sign_str, 'fpOKzILEajkqgSpr9VvU98FwAgIRcX&')
payload = param_to_str + '&Signature=' + urllib.parse.quote_plus(sign_true)
response = requests.post(url, headers=headers, data=payload, proxies=proxies, verify=False)
print(response)
print(response.text)
def hmac_sha1(data, key):
# 密钥
secret_key = b"YSKfst7GaVkXwZYvVihJsKF9r89koz&"
# 使用hmac.new函数创建一个HMAC对象,指定消息和密钥,并设置SHA1算法
hmac_sha1 = hmac.new(key.encode('utf-8'), data.encode('utf-8'), hashlib.sha1)
# 获取HMAC值,默认返回二进制数据
hmac_digest = hmac_sha1.digest()
b64 = base64.b64encode(hmac_digest).decode('utf-8')
return b64
def md5_encrypt_text(decrypt_text: str) -> str:
"""
md5加密
:param decrypt_text: 明文
:return: 密文
"""
return md5(decrypt_text.encode('utf8')).hexdigest()
# 对象转拼接字符串
def obj_sort_str(data):
sorted_keys = sorted(data.keys())
# 使用列表推导式构建排序后的 key=value 字符串列表
sorted_params = [f"{key}={data[key]}" for key in sorted_keys]
# 使用 join 函数将列表中的字符串用 '&' 连接起来
param_str = "&".join(sorted_params)
return param_str
def test():
param = {'AccessKeyId': 'LTAI5tSEBwYMwVKAQGpxmvTd',
'Action': 'InitCaptcha',
'CertifyId': 'fdmjQDfWZA',
'Format': 'JSON',
'Language': 'cn',
'DeviceToken': 'V0VCI2FiMDM0ZWMwNjQzZjkxMzk5ZWIzM2UwNjJkYzdmYWUxLWgtMTcyNDAyNzAwNjA5OS0xNmZhYjUzOTQwZTE0YWEwYjkzNGFjOWE1NmM5MDcyOSNSQWhnc1Y5bzFiMTlIN0lSS2s1ZDB6UUJ2djlNaDh2VEVicjRmNERma2kzUy9sMFpuVUw3WTZrbnZxL2tlVmVSdVNwMThSdC9Fb1JkWmtJVkRMZ1dDdDBZVHYyUEN3WWZWK05yOUFadEJFajFZSjBJOEZRb2V4NVR5WHlFVmlpQVNXNlRiTjJydFpwdE93cjVyZXVaVlZXc0dwWnQzSHdnZVBJTGkwcTFFc3BGaWxtdnFUOEJDb1BiSDZPL1ByT2tpRGVwN3N0K2RnUlBVR2Y0TXJ3Uzl1aGZWTGduaU84NzRVcmVia28zS0luekIwTktUVmJwb3VXQTJnL1ZSMlVpMURtRTlpWWw3d2VSaUxkNFJXbEtLejhXeGozcDhPUFZBd1VIM3Urazh2SkpuNTlnQ0loZEQ4MUtGYmtGK052VElzRzAxa2hmR3RLNkduM2ZWbVhiTDFHV1pwbTgxcG5BQTFNSU1sSkJuYmQrWDZlenpjTktYaWZ1Qm5HSEtTSWQ2ZnhHZWNkWnVRMndRYUtSZU9EbjBmbXl5YjdweXRzZFYyUzJrNTVFakp0K2RFcVpNSGR0VDJyOTZXUU81K09GUDVQbEZGbHpDczV0a3lGdGozUnRCSHFTdS9nQlp6M2VTQnU0Q0R2bXQ5a3J3cmRzVWFlVVlERGpLTzlRTGUyUytGZjNWTXg0NmY3SWVvbjZzYjVpZ3Y4bnZyM0Rnd1dPUWh0NjBIL1BNNVFzYjRDUjkzZFZpUlU0dTdFSllzaUQjMTEyI2U3OTI5MDdiNTRiZWFiNTQ1YjE1NDQzMjgyN2I5ZTRj',
'SceneId': 'fdh8368b',
'SignatureMethod': 'HMAC-SHA1',
'SignatureNonce': '032b7551-c89f-4d9b-bcfb-0e7886e904bf',
'SignatureVersion': '1.0',
'Timestamp': urllib.parse.quote('2024-08-19T00:27:58Z'),
'Version': '2023-03-05'
}
param_str = obj_sort_str(param)
sign_str = f'POST&%2F&{urllib.parse.quote_plus(param_str)}'
print('>>>>>>>>', sign_str)
sign_true = hmac_sha1(sign_str, 'YSKfst7GaVkXwZYvVihJsKF9r89koz&')
print(sign_true, '???')
def aes_cbc_decrypt_text(_text: str, key: str, iv="", method="base64") -> str:
"""
AES解密
:param _text: 密文
:param key: 密钥
:param iv: 密钥偏移量,只有CBC模式有
:param method: 用base64解密还是16进制字符串
:return:解密后的数据
"""
aes = AES.new(key.encode('utf-8'), AES.MODE_CBC, iv.encode('utf-8'))
if method == "base64":
decrypt_text = aes.decrypt(base64.b64decode(_text)).decode('utf8')
else:
decrypt_text = aes.decrypt(a2b_hex(_text)).decode('utf8')
return decrypt_text.strip()
def aes_cbc_encrypt_text(_text: str, key: str, iv="", method="base64", m_pad='pkcs7') -> str:
"""
AES加密
:param _text: 明文
:param key: 密钥
:param iv: 密钥偏移量,只有CBC模式有
:param method: 用base64加密还是16进制字符串
:param m_pad: 补位方式
:return: 密文
"""
aes = AES.new(key.encode('utf-8'), AES.MODE_CBC, iv.encode('utf-8'))
encrypt_text = aes.encrypt(pad(_text.encode('utf-8'), AES.block_size, style=m_pad))
if method == "base64":
return base64.b64encode(encrypt_text).decode()
elif method == "iv_arr":
result_bytes = iv.encode("utf-8") + encrypt_text
return base64.b64encode(result_bytes).decode()
else:
return b2a_hex(encrypt_text).decode()
def aes_ecb_encrypt_text(_text: str, key: str, method="base64", m_pad='pkcs7') -> str:
"""
AES加密
:param _text: 明文
:param key: 密钥
:param method: 用base64加密还是16进制字符串
:param m_pad: 补位方式
:return: 密文
"""
aes = AES.new(key.encode('utf-8'), AES.MODE_ECB)
encrypt_text = aes.encrypt(pad(_text.encode('utf-8'), AES.block_size, style=m_pad))
if method == "base64":
return base64.b64encode(encrypt_text).decode()
else:
return b2a_hex(encrypt_text).decode()
def aes_ecb_decrypt_text(_text: str, key: str, method="base64") -> str:
"""
AES解密
:param _text: 密文
:param key: 密钥
:param method: 用base64解密还是16进制字符串
:return:解密后的数据
"""
aes = AES.new(key.encode('utf-8'), AES.MODE_ECB)
if method == "base64":
decrypt_text = aes.decrypt(base64.b64decode(_text)).decode('utf8')
else:
decrypt_text = aes.decrypt(a2b_hex(_text)).decode('utf8')
return decrypt_text.strip()
# 压缩
def text_encoder(data: str):
# 使用je函数进行UTF-8编码
data_byte = data.encode('utf-8')
# 使用zlib库进行压缩
compressed = zlib.compress(data_byte)
# 使用base64进行编码
return base64.b64encode(compressed).decode('utf-8')
# 解压
def text_decoder(data: str):
# 使用je函数进行UTF-8编码
data_byte = base64.b64decode(data)
# 使用zlib库进行压缩
compressed = zlib.decompress(data_byte)
# 使用base64进行编码
return compressed.decode('utf-8')
def get_device_token(config):
env = [
"W.10030",
"",
"",
"",
"",
"Win32",
"WeChat",
"8.0.45.2521",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"63",
"",
"8",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"d57f20fcf75a171f408d067e1f72f952",
"",
"8",
"",
"Android",
"11",
"",
"",
"",
"",
"101.17.217.107",
"",
"true",
"",
"",
"700*400",
"",
"1",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"saf-captcha",
"",
"",
"",
"3HTz8ltU3tew85f2Yh9SaNffDOC7XPjXDlHoZ1SS", # _c_WBKFRo 取cookies
"1724027006212",
"TbRBea0TsuVF19EBJT9hvm8mA89aNKXvPOPGh8qmkp", # spse _l_KPLiPs //42位随机数
"",
"mobile",
"",
"",
"9d4568c009d203ab10e33ea9953a0264",
"",
"",
"",
"",
"",
"",
"",
"",
"1724027274359",
"MSMwIzAjMCMwIzAjMCMwIzAjMCMwIzAjMCMwIzAjMCMwIzA=",
"1",
"1",
"true",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
""
]
env = '#'.join(env)
env = aes_cbc_encrypt_text(env, config['key'], iv='0123456789ABCDEF')
list = [
"WEB",
config['secretKey'],
env,
"112",
"daye,raolewoba!"
]
sign = '#'.join(list)
sign = md5_encrypt_text(sign)
list[4] = sign
list_str = '#'.join(list)
return base64.b64encode(list_str.encode('utf8')).decode('utf8')
# 提交信息与验证滑块
def apply_code(data):
url = "https://fapi.appykt.com/parking-system/visitor/applyCode"
headers = {
"Accept": "*/*",
"Accept-Language": "zh-CN,zh;q=0.9",
"Cache-Control": "no-cache",
"Connection": "keep-alive",
"Content-Type": "application/json",
"Origin": "https://app.appykt.com",
"Park-Mobile-Auth": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJuYmYiOjE3MjMxNjU1MDcsIm9wZW5JZCI6Im9WSFhDMWI0VGswLVVxa0NtMG11S2NuY3IzWFUiLCJhcHBJZCI6Ind4MTQ3MTZhOTBhMTE3NTkwNyIsImV4cCI6MTcyNDgwNTc2OX0.bb1O_Ie_jV5f1EUKnIBTkwyOCp0ubOJQYvgZ4toTaHQ",
"Pragma": "no-cache",
"Referer": "https://app.appykt.com/",
"Sec-Fetch-Dest": "empty",
"Sec-Fetch-Mode": "cors",
"Sec-Fetch-Site": "same-site",
"User-Agent": "Mozilla/5.0 (Linux; Android 11; M2002J9E Build/RKQ1.200826.002; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/92.0.4515.131 Mobile Safari/537.36 MMWEBID/4339 MicroMessenger/8.0.45.2521(0x28002D3D) WeChat/arm64 Weixin NetType/WIFI Language/zh_CN ABI/arm64",
"sec-ch-ua": "\"\"",
"sec-ch-ua-platform": "\"\""
}
try:
response = requests.post(url, headers=headers, data=data.encode('unicode_escape'), proxies=proxies,
verify=False)
return aes_ecb_decrypt_text(response.text, '76ede6972caa4ba9')
except Exception as e:
return False
# 前景图是背景 背景图是缺口
def identify_gap(fg, bg):
bg_img = cv2.imdecode(np.asarray(bytearray(bg), dtype=np.uint8), 0) # 背景图片
bg_img2 = bg_img.copy() # 背景图片
bg_pic2 = cv2.cvtColor(bg_img2, cv2.COLOR_GRAY2RGB)
tp_img = cv2.imdecode(np.asarray(bytearray(fg), dtype=np.uint8), 0) # 缺口图片
# 识别图片边缘
bg_img[bg_img < 60] = 0
bg_img[bg_img >= 60] = 255
bg_edge = cv2.Canny(bg_img, 0, 20)
tp_edge = cv2.Canny(tp_img, 100, 200)
# 转换图片格式
bg_pic = cv2.cvtColor(bg_edge, cv2.COLOR_GRAY2RGB)
tp_pic = cv2.cvtColor(tp_edge, cv2.COLOR_GRAY2RGB)
cv2.imshow('666', bg_pic)
cv2.waitKey()
# 缺口匹配
s = cv2.matchTemplate(bg_pic, tp_pic, cv2.TM_CCOEFF_NORMED)
min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(s) # 寻找最优匹配
# 绘制方框
th, tw = tp_pic.shape[:2]
tl = max_loc # 左上角点的坐标
br = (tl[0] + tw, tl[1] + th) # 右下角点的坐标
# cv2.rectangle(bg_pic2, tl, br, (0, 255, 255), 2) # 绘制矩形
# cv2.imwrite("3.png", bg_pic2)
distance = tl[0]
h, w = tp_img.shape[:2]
start_point = (distance, 0) # x=201, y=0
end_point = (distance, h - 1) # x=201, y=图像高度-1
color = (255, 0, 0) # BGR颜色:红色
thickness = 2 # 线条粗细
cv2.line(tp_img, start_point, end_point, color, thickness)
# cv2.imshow('image', tp_img)
cv2.imwrite("3.png", tp_img)
return distance
def get_gap(bg, cut):
return identify_gap(bg, cut)
def get_img(url):
try:
return requests.get(url).content
except Exception as e:
print('验证码出错')
return False
def process():
# 获取验证码与配置
res = init_captcha()
if not res:
print('获取验证码失败》》》', res)
Image = res['Image']
PuzzleImage = res['PuzzleImage']
DeviceConfig = res['DeviceConfig']
DeviceConfig = aes_cbc_decrypt_text(DeviceConfig, '87f879f135f27da7', '0123456789ABCDEF')
dev_config_arr = DeviceConfig.split('#')
config = {
'CertifyId': res['CertifyId'],
'key': base64.b64decode(dev_config_arr[0]).decode('utf8'),
'secretKey': dev_config_arr[2],
# ab034ec0643f91399eb33e062dc7fae1-h-1723520526944-4a95e7f819994f06b49006a7b2728405
'timestamp': dev_config_arr[7],
'ip': dev_config_arr[8],
}
bg = get_img(f'https://static-captcha.aliyuncs.com/{Image}')
cut = get_img(f'https://static-captcha.aliyuncs.com/{PuzzleImage}')
if bg and cut:
distance = get_gap(bg, cut)
print('x坐标 >>> ', distance)
# 组装log2
env_list = env_init(config)
env_encrypt = aes_cbc_encrypt_text('#'.join(env_list), config['key'], iv='0123456789ABCDEF')
handle_list = [
config['secretKey'],
env_encrypt,
aes_cbc_encrypt_text('saf-captcha', config['key'], iv='0123456789ABCDEF'),
aes_cbc_encrypt_text('W.10030', config['key'], iv='0123456789ABCDEF'),
"",
aes_cbc_encrypt_text('1723797627765', config['key'], iv='0123456789ABCDEF')
]
handle_list_str = '#'.join(handle_list)
handle_list_str_b64 = base64.b64encode(handle_list_str.encode('utf8')).decode('utf8')
last_arr = [
"ab034ec0643f91399eb33e062dc7fae1",
"W",
aes_cbc_encrypt_text('W.10030#saf-captcha#fdh8368b', config['key'], iv='0123456789ABCDEF'),
"W20220202",
"CLOUD",
"142",
"501",
handle_list_str_b64
]
last_str = '#'.join(last_arr).strip()
last_str_encrypt = aes_cbc_encrypt_text(last_str, 'a549a55c60a39aa0', iv='0123456789ABCDEF')
device_log2(last_str_encrypt)
# 组装log3
track = get_track(config['timestamp'], distance)
track = json.dumps(track, separators=(',', ':'))
data1 = [
config['secretKey'],
aes_cbc_encrypt_text(track, config['key'], iv='0123456789ABCDEF'), # 轨迹
aes_cbc_encrypt_text('saf-captcha', config['key'], iv='0123456789ABCDEF'),
aes_cbc_encrypt_text('W.10030', config['key'], iv='0123456789ABCDEF'),
"",
aes_cbc_encrypt_text('1724027274349', config['key'], iv='0123456789ABCDEF')
]
data1 = '#'.join(data1)
data1 = base64.b64encode(data1.encode('utf8')).decode('utf8')
data2 = [
config['secretKey'],
aes_cbc_encrypt_text('1#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0', config['key'], iv='0123456789ABCDEF'),
aes_cbc_encrypt_text('saf-captcha', config['key'], iv='0123456789ABCDEF'),
aes_cbc_encrypt_text('W.10030', config['key'], iv='0123456789ABCDEF'),
"",
aes_cbc_encrypt_text('1724027274348', config['key'], iv='0123456789ABCDEF')
]
data2 = '#'.join(data2)
data2 = base64.b64encode(data2.encode('utf8')).decode('utf8')
data3 = [
"511",
data2 + '-504',
data1
]
data3 = '#'.join(data3)
data3 = base64.b64encode(data3.encode('utf8')).decode('utf8')
data4 = [
"ab034ec0643f91399eb33e062dc7fae1",
"W",
aes_cbc_encrypt_text('W.10030#saf-captcha#fdh8368b', config['key'], iv='0123456789ABCDEF'),
"W20220202",
"CLOUD",
"74",
data3
]
data4 = '#'.join(data4)
data_log3 = aes_cbc_encrypt_text(data4, 'a549a55c60a39aa0', iv='0123456789ABCDEF')
device_log3(data_log3)
device_token = get_device_token(config)
track = get_track(config['timestamp'], distance)
track = json.dumps(track, separators=(',', ':'))
compress = text_encoder(track)
res = aes_cbc_encrypt_text(compress, '3e627e1b4c63f913', iv='0123456789ABCDEF')
verify = {
"sceneId": "fdh8368b",
"certifyId": config['CertifyId'],
"deviceToken": device_token,
"data": res
}
payload = {
"parkId": "10162606",
"mobileNumber": "18585478545",
"visitDate": "2024-08-19",
"uid": "13025454444",
"carNumber": "冀CJJJJ7",
"verifyParam": json.dumps(verify, separators=(',', ':'))
}
payload_json = json.dumps(payload, separators=(',', ':'))
payload_json_encrypt = aes_ecb_encrypt_text(payload_json, '76ede6972caa4ba9')
verify_res = apply_code(payload_json_encrypt)
print('验证结果', verify_res)
print(get_captcha(device_token, config['CertifyId']))
if __name__ == '__main__':
process()