commit
a4b10b13a8
14 changed files with 1019 additions and 0 deletions
@ -0,0 +1,70 @@ |
|||||
|
import warnings |
||||
|
|
||||
|
import time |
||||
|
from datetime import datetime |
||||
|
|
||||
|
import requests.utils |
||||
|
|
||||
|
from jdseckillAPIv2 import JDSecKillAPI |
||||
|
from tools.mylogger import logger |
||||
|
|
||||
|
warnings.filterwarnings('ignore') |
||||
|
from concurrent.futures import ThreadPoolExecutor, wait |
||||
|
|
||||
|
|
||||
|
class JDSecKillSubmit(JDSecKillAPI): |
||||
|
|
||||
|
def __init__(self, sku, ck): |
||||
|
super().__init__(sku=sku, ck=ck) |
||||
|
self.sku = sku |
||||
|
self.ck = ck |
||||
|
|
||||
|
def log(self, str_p): |
||||
|
logger.info(str_p) |
||||
|
|
||||
|
def doKill(self, sk, order_data): |
||||
|
resp_json = self.submit_order(order_data=order_data, sk=sk) |
||||
|
if resp_json is not None: |
||||
|
txt = order_data['address']['name'] + "抢购结果:" + str(resp_json) |
||||
|
self.log(txt) |
||||
|
if resp_json['success']: |
||||
|
self.send_message(order_data['address']['name'] + '抢购成功, 订单:' + str(resp_json)) |
||||
|
|
||||
|
def appoint_task(self): |
||||
|
try: |
||||
|
resp_json = self.appoint_sku() |
||||
|
print("预约结果:%s" % str(resp_json)) |
||||
|
self.log('appoint:' + str(resp_json)) |
||||
|
except Exception as e: |
||||
|
print(str(e)) |
||||
|
|
||||
|
def killSku(self): |
||||
|
|
||||
|
try: |
||||
|
token_params = self.get_token_key() |
||||
|
print(datetime.now()) |
||||
|
divide_url = self.get_appjmp(token_params=token_params) |
||||
|
print(datetime.now()) |
||||
|
captcha_url = self.get_divide(divide_url=divide_url) |
||||
|
print(datetime.now()) |
||||
|
seckill_url = self.get_captcha(captcha_url=captcha_url) |
||||
|
print(datetime.now()) |
||||
|
|
||||
|
# todo 测试url |
||||
|
# seckill_url = 'https://marathon.jd.com/seckillM/seckill.action?skuId=' + self.sku + '&num=1&rid=1639830212' |
||||
|
resp = self.visit_seckill(seckill_url=seckill_url) |
||||
|
|
||||
|
order_data = self.init_action() |
||||
|
print(datetime.now()) |
||||
|
if order_data is not None: |
||||
|
for k in range(50): |
||||
|
sk_val = self.get_tak() |
||||
|
print("计算sk:%s" % str(sk_val)) |
||||
|
self.doKill(sk_val, order_data) |
||||
|
time.sleep(0.5) |
||||
|
return True |
||||
|
|
||||
|
return False |
||||
|
except Exception as e: |
||||
|
print(str(e)) |
||||
|
return False |
@ -0,0 +1,52 @@ |
|||||
|
import json |
||||
|
import time |
||||
|
|
||||
|
import requests |
||||
|
|
||||
|
|
||||
|
class JDTimer: |
||||
|
|
||||
|
def __init__(self): |
||||
|
self.headers = { |
||||
|
'user-agent': 'okhttp/3.12.1;jdmall;android;version/10.5.0;build/95837;', |
||||
|
'content-type': 'application/x-www-form-urlencoded', |
||||
|
} |
||||
|
self.session = requests.Session() |
||||
|
try: |
||||
|
self.jd_time() |
||||
|
except Exception as e: |
||||
|
print(e) |
||||
|
|
||||
|
def jd_time(self): |
||||
|
""" |
||||
|
从京东服务器获取时间毫秒 |
||||
|
:return: |
||||
|
""" |
||||
|
url = 'https://api.m.jd.com/client.action?functionId=queryMaterialProducts&client=wh5' |
||||
|
ret = self.session.get(url, headers=self.headers, allow_redirects=False, verify=False).text |
||||
|
js = json.loads(ret) |
||||
|
|
||||
|
return int(js["currentTime2"]) |
||||
|
|
||||
|
def local_time(self): |
||||
|
""" |
||||
|
获取本地毫秒时间 |
||||
|
:return: |
||||
|
""" |
||||
|
return int(round(time.time() * 1000)) |
||||
|
|
||||
|
def local_jd_time_diff(self): |
||||
|
""" |
||||
|
计算本地与京东服务器时间差 |
||||
|
:return: |
||||
|
""" |
||||
|
try: |
||||
|
return self.local_time() - self.jd_time() |
||||
|
except Exception as e: |
||||
|
print(e) |
||||
|
return 0 |
||||
|
|
||||
|
if __name__ == '__main__': |
||||
|
jdtimer = JDTimer() |
||||
|
for i in range(5): |
||||
|
print(jdtimer.local_jd_time_diff()) |
@ -0,0 +1,75 @@ |
|||||
|
import time |
||||
|
import sys |
||||
|
import os |
||||
|
|
||||
|
|
||||
|
curPath = os.path.abspath(os.path.dirname(__file__)) |
||||
|
rootPath = os.path.split(curPath)[0] |
||||
|
sys.path.append(rootPath) |
||||
|
|
||||
|
from api_timer import JDTimer |
||||
|
from tools import utils |
||||
|
from JDMain import JDSecKillSubmit |
||||
|
from tools.mylogger import logger |
||||
|
|
||||
|
|
||||
|
class JD: |
||||
|
|
||||
|
def __init__(self): |
||||
|
sku = '100012043978' |
||||
|
|
||||
|
def log(self, str_p): |
||||
|
logger.info(str_p) |
||||
|
|
||||
|
def yuyueSku(self, sku, ck): |
||||
|
self.jdapi = JDSecKillSubmit(sku, ck) |
||||
|
self.jdapi.appoint_task() |
||||
|
|
||||
|
def killSku(self): |
||||
|
for i in range(5): |
||||
|
print('第%d次kill---------------------------->' % i) |
||||
|
result = self.jdapi.killSku() |
||||
|
if result: |
||||
|
break |
||||
|
|
||||
|
def syncTime(self): |
||||
|
jdTimer = JDTimer() |
||||
|
return jdTimer.local_jd_time_diff() |
||||
|
|
||||
|
|
||||
|
if __name__ == '__main__': |
||||
|
|
||||
|
jd = JD() |
||||
|
jd.log("正在读取cookie") |
||||
|
file = open("cookie-xqs.txt") |
||||
|
ck = file.read() |
||||
|
ck = 'pin=jd_694172ad51580;wskey=AAJgfXWSAEBLNQvLpLSYBYcBCqSXPF0LSFJksN9TUW-zjHxTQzDHotSD_LUE5EqkKLhBT3r0b3jCYYm33xg21oLFXWdad7mG;whwswswws=ypBVaXEwFjiJxh/kEB/6O2f6fohXOoCM3D8YNlQLR9tc=;unionwsws={"devicefinger":"eidA852c81205asb09A7r2HGTjCoC1RNl7MXytPQPScu2F6yVo+5IRMfDrQg8oI21UoEA0ZlhW+EgFWItSqxk76gpd5LLB389Tk1jXNw+GmMO1H7tOt5","jmafinger":"ypBVaXEwFjiJxh\/kEB\/6O2f6fohXOoCM3D8YNlQLR9tc="};' |
||||
|
jd.log(ck) |
||||
|
|
||||
|
sku = '100012043978' |
||||
|
killTime = '2022-09-24 11:59:59.900' |
||||
|
killTimeTs = utils.getTimeStamp(killTime, format='%Y-%m-%d %H:%M:%S.%f') |
||||
|
|
||||
|
syncedTime = False |
||||
|
hasYuyue = False |
||||
|
|
||||
|
timeDiff = 0 # 时差 |
||||
|
|
||||
|
while True: |
||||
|
nowTimeTs = int(time.time() * 1000) |
||||
|
killDiff = killTimeTs - nowTimeTs |
||||
|
print("时间剩余%s秒" % str(int(killDiff / 1000))) |
||||
|
|
||||
|
if killDiff < 5 * 60 * 1000 and not syncedTime: |
||||
|
syncedTime = True |
||||
|
timeDiff = jd.syncTime() |
||||
|
print("时差:%s" % str(timeDiff)) |
||||
|
killTimeTs = killTimeTs + timeDiff |
||||
|
elif killDiff < 1 * 60 * 1000 and not hasYuyue: |
||||
|
hasYuyue = True |
||||
|
jd.yuyueSku(sku=sku, ck=ck) |
||||
|
elif killDiff < 0: |
||||
|
print("时差:%s" % str(timeDiff)) |
||||
|
jd.killSku() |
||||
|
break |
||||
|
time.sleep(0.01) |
@ -0,0 +1 @@ |
|||||
|
pin=jd_41d74c83f8224;wskey=AAJjKGIcAED51MS4xl3rMhkuKoz3aIdtHgYbbY_gONAtDcvoXgp0nCjPWKcjgXoBw3ZNcm-HVECeryK5NBFQiErqyGbAcqt-;whwswswws=JD012145b9WBZ52FxcoJ166359098310502j1UGQOp_xw1sHnZf2TBLxIAVcI1pr_ptSG7GbI4Jh8JHPzpgXIVd6vHgcp4KUP7bIcL92ot4SobMNdIjsb6CeO0xXfdGg1DB166dh3n~lV6zvij0xVW8O87RwFvqyq8bfocRq2uG0yIAc6GJfPzG3Vt7W-bSkl68yzw3cggRUZpEKUJ0VpkW0x0Q0aGrCFLasnWujHANJMp2D1tUHzbtF-NKQkCBUiGE1ZKdTwYkeVoNQaOoU87ivURTKramyPzaIW67BRI6kPNkr3PLHsHc;unionwsws={"devicefinger":"eidAfa90812247s5vgf0CkxeRgeWBZfWowyK9r4H9Y2h1wPWRDa\/+LyYAJea3ooTv4ePNmFFv1ZArvKR74Nk1rlZWoaTpHUgZCeqmC5Lix6Hz1eGUEN6","jmafinger":"JD012145b9WBZ52FxcoJ166359098310502j1UGQOp_xw1sHnZf2TBLxIAVcI1pr_ptSG7GbI4Jh8JHPzpgXIVd6vHgcp4KUP7bIcL92ot4SobMNdIjsb6CeO0xXfdGg1DB166dh3n~lV6zvij0xVW8O87RwFvqyq8bfocRq2uG0yIAc6GJfPzG3Vt7W-bSkl68yzw3cggRUZpEKUJ0VpkW0x0Q0aGrCFLasnWujHANJMp2D1tUHzbtF-NKQkCBUiGE1ZKdTwYkeVoNQaOoU87ivURTKramyPzaIW67BRI6kPNkr3PLHsHc"}; |
@ -0,0 +1,350 @@ |
|||||
|
import json |
||||
|
import warnings |
||||
|
|
||||
|
import requests |
||||
|
import re |
||||
|
from urllib import parse |
||||
|
import time |
||||
|
|
||||
|
from wxpusher import WxPusher |
||||
|
|
||||
|
from tools import utils |
||||
|
from tools.jd_sign import getSign |
||||
|
|
||||
|
warnings.filterwarnings('ignore') |
||||
|
|
||||
|
|
||||
|
def getUrlParams(url): |
||||
|
res = dict(parse.parse_qsl(url)) |
||||
|
return res |
||||
|
|
||||
|
|
||||
|
def get_cookie_string(cookie): |
||||
|
cookie_string = '' |
||||
|
for cookie_key in cookie.keys(): |
||||
|
cookie_string += '%s=%s;' % (cookie_key, cookie[cookie_key]) |
||||
|
return cookie_string |
||||
|
|
||||
|
|
||||
|
def get_jd_time(): |
||||
|
response = requests.get(url='https://api.m.jd.com/client.action?functionId=queryMaterialProducts&client=wh5') |
||||
|
print(response.json()) |
||||
|
|
||||
|
|
||||
|
def get_sk(data): |
||||
|
data_val = [val for val in data['data'].values()] |
||||
|
n, o, p, q, r, s = data_val[0], data_val[1], data_val[2], data_val[3], data_val[4], data_val[5] |
||||
|
sk_val = '' |
||||
|
if n == 'cca': |
||||
|
sk_val = p[14:19].lower() + o[5:15].upper() |
||||
|
if n == 'ab': # check ok |
||||
|
sk_val = r[10:18] + s[2:13].lower() |
||||
|
if n == 'ch': |
||||
|
sk_val = q.upper() + r[6:10].upper() |
||||
|
if n == 'cbc': # check ok |
||||
|
sk_val = q[3:13].upper() + p[10:19].lower() |
||||
|
if n == 'by': |
||||
|
sk_val = o[5:8] + re.sub('a', 'c', p, flags=re.IGNORECASE) |
||||
|
if n == 'xa': |
||||
|
sk_val = o[1:16] + s[4:10] |
||||
|
if n == 'cza': |
||||
|
sk_val = q[6:19].lower() + s[5:11] |
||||
|
if n == 'cb': |
||||
|
sk_val = s[5:14] + p[2:13].upper() |
||||
|
|
||||
|
return sk_val |
||||
|
|
||||
|
|
||||
|
class JDSecKillAPI: |
||||
|
def __init__(self, sku, ck): |
||||
|
self.skuId = sku |
||||
|
self.s = requests.session() |
||||
|
self.sku = sku |
||||
|
self.ck = ck |
||||
|
self.aid = '' |
||||
|
self.eid = 'eidAccfa8121das3mOM5swaGRcSw7E22kO50H5jjOzSUZLdxjWFZLi3ATsvj875K/RWM0W4ztxrbes6TNeio5uhWCeJIKObRbFo6NaYRyMqYuMJ2MM5D' |
||||
|
self.uuid = '351792042184702-6dd3f46ae26a' |
||||
|
self.uts = '0f31TVRjBSsqndu4/jgUPz6uymy50MQJAUhDDPnNIByQiRdjk5SK6CXmdShdxGaPRUd2+o8JNufp2fsgzyZpKhao+6lXsd3TXF8+jFmN/08eWFOjD36AXn3DPYPoc8MKL9ccf40wpTgO1wSP1oliin/fcMzzPHSxzINfo/svdCXHzPsMY3eZLWP0KGqPLr5fXA1RZRoBs4xl/IYv7E80OQ==' |
||||
|
self.wifiBssid = '' |
||||
|
self.ua = 'AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/83.0.4103.106 Mobile Safari/537.36' |
||||
|
|
||||
|
def appoint_sku(self): |
||||
|
headers = { |
||||
|
'user-agent': 'okhttp/3.12.1;jdmall;android;version/10.5.0;build/95837;', |
||||
|
'content-type': 'application/x-www-form-urlencoded', |
||||
|
'cookie': self.ck, |
||||
|
'jdc-backup': self.ck, |
||||
|
} |
||||
|
|
||||
|
ts = int(time.time() * 1000) |
||||
|
uuid = self.uuid |
||||
|
ep = utils.get_ep(ts, uuid) |
||||
|
|
||||
|
query_params = { |
||||
|
'functionId': 'appoint', |
||||
|
'clientVersion': '10.5.0', |
||||
|
'build': '95837', |
||||
|
'client': 'android', |
||||
|
'd_brand': 'HUAWEI', |
||||
|
'd_model': 'LIO-AN00', |
||||
|
'osVersion': '7.1.2', |
||||
|
'screen': '1920*1080', |
||||
|
'partner': 'hhqj02', |
||||
|
'aid': self.aid, |
||||
|
'eid': self.eid, |
||||
|
'sdkVersion': '29', |
||||
|
'lang': 'zh_CN', |
||||
|
'harmonyOs': '0', |
||||
|
'uuid': self.uuid, |
||||
|
'area': '', |
||||
|
'networkType': 'wifi', |
||||
|
'wifiBssid': self.wifiBssid, |
||||
|
'uts': self.uts, |
||||
|
'uemps': '0-0', |
||||
|
'ext': '{"prstate":"0","pvcStu":"1"}', |
||||
|
'ef': '1', |
||||
|
'ep': json.dumps(ep, ensure_ascii=False, separators=(',', ':')), |
||||
|
} |
||||
|
reserve_url = 'https://api.m.jd.com/client.action' |
||||
|
|
||||
|
body = {"autoAddCart": "0", "bsid": "", "check": "0", "ctext": "", "isShowCode": "0", "mad": "0", |
||||
|
"skuId": self.skuId, "type": "1"} |
||||
|
|
||||
|
plainTextDic = { |
||||
|
"st": ts, # 毫秒级时间戳 |
||||
|
"sv": "120", |
||||
|
"functionId": query_params['functionId'], |
||||
|
"uuid": uuid, |
||||
|
"client": query_params['client'], |
||||
|
"clientVersion": query_params['clientVersion'], |
||||
|
"body": json.dumps(body, ensure_ascii=False, separators=(',', ':')) |
||||
|
} |
||||
|
st, sign, sv = getSign(plainTextDic) |
||||
|
|
||||
|
query_params.update(st=st) |
||||
|
query_params.update(sign=sign) |
||||
|
query_params.update(sv=sv) |
||||
|
|
||||
|
data = {'body': json.dumps(body, ensure_ascii=False, separators=(',', ':'))} |
||||
|
|
||||
|
response = self.s.post(url=reserve_url, |
||||
|
params=query_params, |
||||
|
data=data, |
||||
|
headers=headers, |
||||
|
allow_redirects=False, |
||||
|
verify=False, |
||||
|
timeout=3) |
||||
|
return response.json() |
||||
|
|
||||
|
def get_token_key(self): |
||||
|
headers = { |
||||
|
'user-agent': 'okhttp/3.12.1;jdmall;android;version/10.5.0;build/95837;', |
||||
|
'content-type': 'application/x-www-form-urlencoded', |
||||
|
'cookie': self.ck, |
||||
|
'jdc-backup': self.ck, |
||||
|
} |
||||
|
|
||||
|
ts = int(time.time() * 1000) |
||||
|
uuid = self.uuid |
||||
|
ep = utils.get_ep(ts, uuid) |
||||
|
|
||||
|
query_params = { |
||||
|
'functionId': 'genToken', |
||||
|
'clientVersion': '10.5.0', |
||||
|
'build': '95837', |
||||
|
'client': 'android', |
||||
|
'd_brand': 'HUAWEI', |
||||
|
'd_model': 'LIO-AN00', |
||||
|
'osVersion': '7.1.2', |
||||
|
'screen': '1920*1080', |
||||
|
'partner': 'hhqj02', |
||||
|
'aid': self.aid, |
||||
|
'eid': self.eid, |
||||
|
'sdkVersion': '29', |
||||
|
'lang': 'zh_CN', |
||||
|
'harmonyOs': '0', |
||||
|
'uuid': self.uuid, |
||||
|
'area': '', |
||||
|
'networkType': 'wifi', |
||||
|
'wifiBssid': self.wifiBssid, |
||||
|
'uts': self.uts, |
||||
|
'uemps': '0-0', |
||||
|
'ext': '{"prstate":"0","pvcStu":"1"}', |
||||
|
'ef': '1', |
||||
|
'ep': json.dumps(ep, ensure_ascii=False, separators=(',', ':')), |
||||
|
} |
||||
|
|
||||
|
body = {"action": "to", "to": "https://divide.jd.com/user_routing?skuId="+self.sku} |
||||
|
|
||||
|
plainTextDic = { |
||||
|
"st": ts, # 毫秒级时间戳 |
||||
|
"sv": "120", |
||||
|
"functionId": query_params['functionId'], |
||||
|
"uuid": uuid, |
||||
|
"client": query_params['client'], |
||||
|
"clientVersion": query_params['clientVersion'], |
||||
|
"body": json.dumps(body, ensure_ascii=False, separators=(',', ':')) |
||||
|
} |
||||
|
st, sign, sv = getSign(plainTextDic) |
||||
|
|
||||
|
query_params.update(st=st) |
||||
|
query_params.update(sign=sign) |
||||
|
query_params.update(sv=sv) |
||||
|
|
||||
|
data = {'body': json.dumps(body, ensure_ascii=False, separators=(',', ':'))} |
||||
|
|
||||
|
response = self.s.post(url='https://api.m.jd.com/client.action', |
||||
|
params=query_params, |
||||
|
data=data, |
||||
|
headers=headers, |
||||
|
allow_redirects=False, |
||||
|
verify=False, |
||||
|
timeout=3) |
||||
|
# token_key = response.json()['tokenKey'] |
||||
|
# print('Token Key: ----------> %s' % response.json()) |
||||
|
# print(response.status_code) |
||||
|
json_obj = response.json() |
||||
|
print('Get genToken--------------->%s' % str(json_obj)) |
||||
|
return json_obj |
||||
|
|
||||
|
def get_appjmp(self, token_params): |
||||
|
headers = { |
||||
|
'user-agent': self.ua |
||||
|
} |
||||
|
appjmp_url = token_params['url'] |
||||
|
params = { |
||||
|
'to': 'https://divide.jd.com/user_routing?skuId=%s' % self.skuId, |
||||
|
'tokenKey': token_params['tokenKey'] |
||||
|
} |
||||
|
|
||||
|
response = self.s.get(url=appjmp_url, params=params, allow_redirects=False, verify=False, headers=headers) |
||||
|
print('Get Appjmp跳转链接-------------->%s' % response.headers['Location']) |
||||
|
return response.headers['Location'] |
||||
|
|
||||
|
def get_divide(self, divide_url): |
||||
|
headers = { |
||||
|
'user-agent': self.ua |
||||
|
} |
||||
|
response = self.s.get(url=divide_url, allow_redirects=False, verify=False, headers=headers) |
||||
|
print('Get Divide跳转链接-------------->%s' % response.headers['Location']) |
||||
|
return response.headers['Location'] |
||||
|
|
||||
|
def get_captcha(self, captcha_url): |
||||
|
headers = { |
||||
|
'user-agent': self.ua |
||||
|
} |
||||
|
response = self.s.get(url=captcha_url, allow_redirects=False, verify=False, headers=headers) |
||||
|
print('Get Captcha跳转链接-------------->%s' % response.headers['Location']) |
||||
|
return response.headers['Location'] |
||||
|
|
||||
|
def visit_seckill(self, seckill_url): |
||||
|
headers = { |
||||
|
'user-agent': self.ua |
||||
|
} |
||||
|
response = self.s.get(url=seckill_url, allow_redirects=False, verify=False, headers=headers) |
||||
|
return response |
||||
|
|
||||
|
def init_action(self, num=1): |
||||
|
|
||||
|
try: |
||||
|
headers = { |
||||
|
'user-agent': self.ua, |
||||
|
'Connection': 'keep-alive' |
||||
|
} |
||||
|
init_action_url = 'https://marathon.jd.com/seckillnew/orderService/init.action' |
||||
|
data = { |
||||
|
'sku': self.skuId, |
||||
|
'num': num, |
||||
|
'id': 0, |
||||
|
'provinceId': 0, |
||||
|
'cityId': 0, |
||||
|
'countyId': 0, |
||||
|
'townId': 0, |
||||
|
} |
||||
|
response = self.s.post(url=init_action_url, data=data, allow_redirects=False, verify=False, headers=headers) |
||||
|
print('init action返回数据:%s' % response.text) |
||||
|
return response.json() |
||||
|
except Exception as e: |
||||
|
print(str(e)) |
||||
|
return None |
||||
|
|
||||
|
|
||||
|
def get_tak(self): |
||||
|
try: |
||||
|
headers = { |
||||
|
'user-agent': self.ua, |
||||
|
'Connection': 'keep-alive' |
||||
|
} |
||||
|
tak_url = 'https://tak.jd.com/t/871A9?_t=%d' % (int(round(time.time() * 1000))) |
||||
|
response = self.s.get(url=tak_url, allow_redirects=False, verify=False, headers=headers) |
||||
|
sk_val = get_sk(data=response.json()) |
||||
|
return sk_val |
||||
|
except Exception as e: |
||||
|
print(str(e)) |
||||
|
return '' |
||||
|
|
||||
|
def submit_order(self, order_data, sk): |
||||
|
try: |
||||
|
headers = { |
||||
|
'user-agent': self.ua, |
||||
|
'Connection': 'keep-alive' |
||||
|
} |
||||
|
submit_order_url = 'https://marathon.jd.com/seckillnew/orderService/submitOrder.action?skuId=%s' % self.skuId |
||||
|
address_info = order_data['address'] |
||||
|
invoice_info = order_data['invoiceInfo'] |
||||
|
data = { |
||||
|
'num': order_data['seckillSkuVO']['num'], |
||||
|
'addressId': address_info['id'], |
||||
|
'yuShou': True, |
||||
|
'isModifyAddress': False, |
||||
|
'name': address_info['name'], |
||||
|
'provinceId': address_info['provinceId'], |
||||
|
'provinceName': address_info['provinceName'], |
||||
|
'cityId': address_info['cityId'], |
||||
|
'cityName': address_info['cityName'], |
||||
|
'countyId': address_info['countyId'], |
||||
|
'countyName': address_info['countyName'], |
||||
|
'townId': address_info['townId'], |
||||
|
'townName': address_info['townName'], |
||||
|
'addressDetail': address_info['addressDetail'], |
||||
|
'mobile': address_info['mobile'], |
||||
|
'mobileKey': address_info['mobileKey'], |
||||
|
'email': '', |
||||
|
'invoiceTitle': invoice_info['invoiceTitle'], |
||||
|
'invoiceContent': invoice_info['invoiceContentType'], |
||||
|
'invoicePhone': invoice_info['invoicePhone'], |
||||
|
'invoicePhoneKey': invoice_info['invoicePhoneKey'], |
||||
|
'invoice': True, |
||||
|
'codTimeType': '3', |
||||
|
'paymentType': '4', |
||||
|
'overseas': '0', |
||||
|
'token': order_data['token'], |
||||
|
'sk': sk, |
||||
|
} |
||||
|
|
||||
|
response = self.s.post(url=submit_order_url, data=data, allow_redirects=False, verify=False, headers=headers) |
||||
|
return response.json() |
||||
|
except Exception as e: |
||||
|
print('submit error--->') |
||||
|
return None |
||||
|
|
||||
|
def send_message(self, content): |
||||
|
try: |
||||
|
# 推送token |
||||
|
PUSH_TOKEN = 'AT_4XxUFvSjSLWTlFhX1nFmIepe1RNoGq8b' |
||||
|
|
||||
|
UIDS = [ |
||||
|
'UID_D77yyDO0pT7K0f1q2UijDTGnGthF', |
||||
|
] |
||||
|
msg = WxPusher.send_message(content, |
||||
|
uids=UIDS, |
||||
|
token=PUSH_TOKEN) |
||||
|
except Exception as e: |
||||
|
print('send_message error--->'+str(e)) |
||||
|
|
||||
|
if __name__ == '__main__': |
||||
|
ck = 'pin=jd_694172ad51580;wskey=AAJgfXWSAEBLNQvLpLSYBYcBCqSXPF0LSFJksN9TUW-zjHxTQzDHotSD_LUE5EqkKLhBT3r0b3jCYYm33xg21oLFXWdad7mG;whwswswws=ypBVaXEwFjiJxh/kEB/6O2f6fohXOoCM3D8YNlQLR9tc=;unionwsws={"devicefinger":"eidA852c81205asb09A7r2HGTjCoC1RNl7MXytPQPScu2F6yVo+5IRMfDrQg8oI21UoEA0ZlhW+EgFWItSqxk76gpd5LLB389Tk1jXNw+GmMO1H7tOt5","jmafinger":"ypBVaXEwFjiJxh\/kEB\/6O2f6fohXOoCM3D8YNlQLR9tc="};' |
||||
|
ck = 'pin=jd_4d36cfba7dab3;wskey=AAJjGfg2AEDbVEKTmVkgEvWx-McNVFq980fU5IHeej0nLaHVNdOtzlTLYBDCEucWGJ4G9teOfEzntfRGd6KQyjXgY3rjDDn1;whwswswws=JD012145b9v1fE5xpOyD1662646298263061cDoZzexYxAp8KLqT9smx6eCUAMi_vgpfvlNGugBkHqboOLvPxFIIgdchS83Af4aCPkH9MZR8ybX3QlO52r5tGF45M9TrieypOzwu3NAoOs0a40rty~w8wI98OE8okFESgoJ3sI8KD1kO1fXEYyQfW7eDyRLBI1VlbD72BRZvaIwvqX8mX245w7Jl7eI9mR2U_2IrtbtCm-NOZyDZr7LWiepMRuTaaO-iRDLr0M_4xyeRgstrh1ombJE27yWpzAQs4PLrFSWhVWGnPf597V0y6FJhG3YaXA;unionwsws={"devicefinger":"eidAea1681212dsbM9nriXryQHq\/kLPLj0nYnTPZ7QyYY2ofy15o7Ohj1DMrIY\/71NnUV3ow\/8dwlD\/hgR5tfjQJNif\/1NbGABbd9A29YETZGl0TuF45","jmafinger":"JD012145b9v1fE5xpOyD1662646298263061cDoZzexYxAp8KLqT9smx6eCUAMi_vgpfvlNGugBkHqboOLvPxFIIgdchS83Af4aCPkH9MZR8ybX3QlO52r5tGF45M9TrieypOzwu3NAoOs0a40rty~w8wI98OE8okFESgoJ3sI8KD1kO1fXEYyQfW7eDyRLBI1VlbD72BRZvaIwvqX8mX245w7Jl7eI9mR2U_2IrtbtCm-NOZyDZr7LWiepMRuTaaO-iRDLr0M_4xyeRgstrh1ombJE27yWpzAQs4PLrFSWhVWGnPf597V0y6FJhG3YaXA"};' |
||||
|
jdapi = JDSecKillAPI('100012043978', ck) |
||||
|
print('预约结果--->', jdapi.appoint_sku()) |
||||
|
print('gentoken结果--->', jdapi.get_token_key('100012043978')) |
@ -0,0 +1,81 @@ |
|||||
|
import time |
||||
|
import sys |
||||
|
import os |
||||
|
curPath = os.path.abspath(os.path.dirname(__file__)) |
||||
|
rootPath = os.path.split(curPath)[0] |
||||
|
sys.path.append(rootPath) |
||||
|
|
||||
|
from multiprocessing import Process |
||||
|
import requests |
||||
|
|
||||
|
from tools import utils |
||||
|
from JDMain import JDSecKillSubmit |
||||
|
from api_timer import JDTimer |
||||
|
|
||||
|
|
||||
|
|
||||
|
def syncTime(): |
||||
|
jdTimer = JDTimer() |
||||
|
return jdTimer.local_jd_time_diff() |
||||
|
|
||||
|
|
||||
|
def yuyueSku(sku, ck): |
||||
|
jdapi = JDSecKillSubmit(sku, ck) |
||||
|
jdapi.appoint_task() |
||||
|
|
||||
|
|
||||
|
def killSku(sku, ck): |
||||
|
jdapi = JDSecKillSubmit(sku, ck) |
||||
|
for i in range(5): |
||||
|
print('第%d次kill---------------------------->' % i) |
||||
|
if jdapi.killSku(): |
||||
|
break |
||||
|
|
||||
|
def work(killTime, ck): |
||||
|
print('ck:', ck) |
||||
|
sku = '100012043978' |
||||
|
killTimeTs = utils.getTimeStamp(killTime, format='%Y-%m-%d %H:%M:%S.%f') |
||||
|
|
||||
|
syncedTime = False |
||||
|
hasYuyue = False |
||||
|
|
||||
|
timeDiff = 0 # 时差 |
||||
|
|
||||
|
while True: |
||||
|
nowTimeTs = int(time.time() * 1000) |
||||
|
killDiff = killTimeTs - nowTimeTs |
||||
|
print("时间剩余%s秒" % str(int(killDiff / 1000))) |
||||
|
|
||||
|
if killDiff < 5 * 60 * 1000 and not syncedTime: |
||||
|
syncedTime = True |
||||
|
timeDiff = syncTime() |
||||
|
print("时差:%s" % str(timeDiff)) |
||||
|
killTimeTs = killTimeTs + timeDiff |
||||
|
elif killDiff < 2 * 60 * 1000 and not hasYuyue: |
||||
|
hasYuyue = True |
||||
|
yuyueSku(sku=sku, ck=ck) |
||||
|
elif killDiff < 0: |
||||
|
print("时差:%s" % str(timeDiff)) |
||||
|
killSku(sku=sku, ck=ck) |
||||
|
break |
||||
|
time.sleep(0.01) |
||||
|
|
||||
|
|
||||
|
if __name__ == '__main__': |
||||
|
|
||||
|
# 抢购时间 |
||||
|
killTime = '2022-11-09 11:59:59.800' |
||||
|
|
||||
|
# cookie |
||||
|
cks = [ |
||||
|
'pin=jd_41d74c83f8224;wskey=AAJjKGIcAED51MS4xl3rMhkuKoz3aIdtHgYbbY_gONAtDcvoXgp0nCjPWKcjgXoBw3ZNcm-HVECeryK5NBFQiErqyGbAcqt-;whwswswws=JD012145b9WBZ52FxcoJ166359098310502j1UGQOp_xw1sHnZf2TBLxIAVcI1pr_ptSG7GbI4Jh8JHPzpgXIVd6vHgcp4KUP7bIcL92ot4SobMNdIjsb6CeO0xXfdGg1DB166dh3n~lV6zvij0xVW8O87RwFvqyq8bfocRq2uG0yIAc6GJfPzG3Vt7W-bSkl68yzw3cggRUZpEKUJ0VpkW0x0Q0aGrCFLasnWujHANJMp2D1tUHzbtF-NKQkCBUiGE1ZKdTwYkeVoNQaOoU87ivURTKramyPzaIW67BRI6kPNkr3PLHsHc;unionwsws={"devicefinger":"eidAfa90812247s5vgf0CkxeRgeWBZfWowyK9r4H9Y2h1wPWRDa\/+LyYAJea3ooTv4ePNmFFv1ZArvKR74Nk1rlZWoaTpHUgZCeqmC5Lix6Hz1eGUEN6","jmafinger":"JD012145b9WBZ52FxcoJ166359098310502j1UGQOp_xw1sHnZf2TBLxIAVcI1pr_ptSG7GbI4Jh8JHPzpgXIVd6vHgcp4KUP7bIcL92ot4SobMNdIjsb6CeO0xXfdGg1DB166dh3n~lV6zvij0xVW8O87RwFvqyq8bfocRq2uG0yIAc6GJfPzG3Vt7W-bSkl68yzw3cggRUZpEKUJ0VpkW0x0Q0aGrCFLasnWujHANJMp2D1tUHzbtF-NKQkCBUiGE1ZKdTwYkeVoNQaOoU87ivURTKramyPzaIW67BRI6kPNkr3PLHsHc"};', |
||||
|
] |
||||
|
|
||||
|
p = [] |
||||
|
for i in range(len(cks)): |
||||
|
p1 = Process(target=work, args=(killTime, cks[i],)) |
||||
|
p1.start() |
||||
|
p.append(p1) |
||||
|
|
||||
|
for i in range(len(cks)): |
||||
|
p[i].join() |
@ -0,0 +1,3 @@ |
|||||
|
requests==2.27.1 |
||||
|
wxpusher==2.2.0 |
||||
|
urllib3==1.26.9 |
@ -0,0 +1,30 @@ |
|||||
|
计算sk:zr7oflx9p335iWYurie |
||||
|
Expecting value: line 1 column 1 (char 0) |
||||
|
Get Divide跳转链接-------------->https://marathon.jd.com/m/captcha.html?sid=b8385a800e93b184ff8bb16a0e79d8aw&skuId=10001 |
||||
|
2043978&mid=rvXgpdduG3wnlgfPzI2wXkvpgNqF4IA9qcWds4ffipY |
||||
|
Get Captcha跳转链接-------------->https://marathon.jd.com/mobile/koFail.html |
||||
|
init action返回数据:{"address":{"addressDetail":"西李村","areaCode":"999999","cityId":2900,"cityName":"济宁市","countyI |
||||
|
d":2917,"countyName":"金乡县","defaultAddress":false,"id":6188735630,"mobile":"133****4689","mobileKey":"f7dcf949de1a7b4 |
||||
|
27463a9dd90f632e1","name":"王秋娟","overseas":0,"phone":"","postCode":"","provinceId":13,"provinceName":"山东","selected |
||||
|
":true,"townId":25860,"townName":"鱼山街道","yuyueAddress":false},"buyNum":2,"code":"200","invoiceInfo":{"invoiceContent |
||||
|
Type":1,"invoicePhone":"133****4689","invoicePhoneKey":"f7dcf949de1a7b427463a9dd90f632e1","invoiceTitle":4,"invoiceType" |
||||
|
:3},"jingdouBO":{"canUseCount":0,"forbidUseJingdou":false,"jingdouDiscount":0,"jingdouSteps":[],"pointsDeductionRate":50 |
||||
|
,"rate":100,"totalCount":179,"usedCount":0},"orderPriceBO":{"couponAbleNum":0,"couponDiscount":0.00,"couponDiscountTotal |
||||
|
":0.00,"couponSelectNum":0,"couponTypeList":[],"freight":0.00,"giftCardAbleNum":0,"giftCardDiscount":0.00,"giftCardSelec |
||||
|
tNum":0,"jingdouDiscount":0,"manjianDiscount":0.00,"orderTax":0.00,"productTotalPrice":1499.00,"redPacketDeductionAmount |
||||
|
":0,"redPacketIsSelected":false,"redPacketTotalAmount":0,"showXuZhongInfo":false,"totalPrice":1499.00,"weight":"1.12","y |
||||
|
unfeiDiscount":0.00},"payment":{"paymentId":4,"paymentName":"在线支付"},"preSaleBO":{"hidePrice":false,"refundDeposit":f |
||||
|
alse},"seckillOrderExt":{},"seckillSkuVO":{"color":"飞天 53%vol 500ml 贵州茅台酒","extMap":{"YuShou":"1","is7ToReturn":" |
||||
|
0","new7ToReturn":"8","thwa":"0","SoldOversea":"0"},"height":0.0,"jdPrice":1499.00,"length":0.0,"num":1,"rePrice":0.00," |
||||
|
size":"","skuId":100012043978,"skuImgUrl":"jfs/t1/204850/31/20522/123067/61af3d74E747493f0/385d705a66b5263b.jpg","skuNam |
||||
|
e":"飞天 53%vol 500ml 贵州茅台酒(带杯)","skuPrice":1499.00,"thirdCategoryId":0.0,"venderName":"京东自营","venderType" |
||||
|
:0,"weight":1.120,"width":0.0},"shipment":{"bundleUuid":"BundleRelation_1125395520593502208","obtainAllCombinationBundle |
||||
|
":"CombinationBundleRelation_1125395520425730051","obtainOrder":"-1719262869","shipmentTimeType":4,"shipmentTimeTypeName |
||||
|
":"标准达","shipmentType":65,"shipmentTypeName":"京东配送","uuid":"101612_1125395520610279424"},"token":"fdc90dde774b3c5 |
||||
|
84b613a8b33050a95","userInfoBO":{"userScore":5525}} |
||||
|
计算sk:6ktun1kxw1gypV4GMMQ |
||||
|
抢购结果:{'appUrl': 'https://mpay.m.jd.com/mpay.1ec8f70280318a51e2bb.html?appId=jd_m_msha&payId=3420cb4f0d7a4424b53f8ae7 |
||||
|
81f542f6', 'orderId': 250387144183, 'pcUrl': '//sko.jd.com/success/success.action?orderId=250387144183&rid=0.88556282118 |
||||
|
81714', 'resultCode': 0, 'skuId': 0, 'success': True, 'totalMoney': '1499.00'} |
||||
|
耗时:941 |
||||
|
Get Divide跳转链接-------------->https://marathon.jd.com/m/captcha.html?sid=b8385a800e93b184ff8bb16a0e79d8aw&skuId=10001 |
@ -0,0 +1,112 @@ |
|||||
|
# -*- coding: utf-8 -*- |
||||
|
class ModifiedBase64(object): |
||||
|
|
||||
|
def __init__(self): |
||||
|
self.aae = ['K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', |
||||
|
'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', |
||||
|
'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', |
||||
|
'8', '9', '+', '/'] |
||||
|
self.aaf = [None] * 128 |
||||
|
|
||||
|
# renamed from: pf |
||||
|
# def m23208pf(self): |
||||
|
i = 0 |
||||
|
i2 = 0 |
||||
|
while True: |
||||
|
bArr = self.aaf |
||||
|
if i2 <= len(bArr) - 1: |
||||
|
bArr[i2] = -1 |
||||
|
i2 += 1 |
||||
|
else: |
||||
|
break |
||||
|
while True: |
||||
|
cArr = self.aae |
||||
|
if i <= len(cArr) - 1: |
||||
|
self.aaf[ord(cArr[i])] = int(i) |
||||
|
i += 1 |
||||
|
else: |
||||
|
return |
||||
|
|
||||
|
def m23207r(self, str_): |
||||
|
result = '' |
||||
|
bArr = bytearray(str_.encode('utf-8')) |
||||
|
|
||||
|
i = 0 |
||||
|
while i <= len(bArr) - 1: |
||||
|
bArr2 = [None] * 4 |
||||
|
b = 0 |
||||
|
i2 = 0 |
||||
|
while i2 <= 2: |
||||
|
i3 = i + i2 |
||||
|
if i3 <= len(bArr) - 1: |
||||
|
bArr2[i2] = (b | ((bArr[i3] & 255) >> ((i2 * 2) + 2))) |
||||
|
b = ((((bArr[i3] & 255) << (((2 - i2) * 2) + 2)) & 255) >> 2) |
||||
|
else: |
||||
|
bArr2[i2] = b |
||||
|
b = 0x40 # SignedBytes.MAX_POWER_OF_TWO; |
||||
|
i2 += 1 |
||||
|
bArr2[3] = b |
||||
|
|
||||
|
i4 = 0 |
||||
|
while i4 <= 3: |
||||
|
if bArr2[i4] <= 63: |
||||
|
result = result + self.aae[bArr2[i4]] |
||||
|
else: |
||||
|
result = result + '=' |
||||
|
i4 += 1 |
||||
|
i += 3 |
||||
|
|
||||
|
return result |
||||
|
|
||||
|
# renamed from: eC |
||||
|
def m23209eC(self, str_): |
||||
|
""" generated source for method m23209eC """ |
||||
|
bys = [] |
||||
|
# bytes = str_.encode('utf-8') |
||||
|
bytes = bytearray(str_.encode('utf-8')) |
||||
|
# print(bytes) |
||||
|
bArr = [None] * len(bytes) |
||||
|
i = 0 |
||||
|
while i <= len(bytes) - 1: |
||||
|
bArr[i] = self.aaf[bytes[i]] |
||||
|
i += 1 |
||||
|
i2 = 0 |
||||
|
while i2 <= len(bArr) - 1: |
||||
|
bArr2 = [None] * 3 |
||||
|
i3 = 0 |
||||
|
i4 = 0 |
||||
|
i7 = 0 |
||||
|
while i4 <= 2: |
||||
|
i5 = i2 + i4 |
||||
|
i6 = i5 + 1 |
||||
|
if i6 <= len(bArr) and bArr[i6] >= 0: |
||||
|
bArr2[i4] = ((bArr[i5] & 255) << ((i4 * 2) + 2)) | ((bArr[i6] & 255) >> (((2 - (i4 + 1)) * 2) + 2)) |
||||
|
i3 += 1 |
||||
|
i4 += 1 |
||||
|
while i7 <= i3 - 1: |
||||
|
bys.append(self.py2ja(bArr2[i7])) |
||||
|
i7 += 1 |
||||
|
i2 += 4 |
||||
|
return bytearray(bys).decode('utf-8') |
||||
|
|
||||
|
def py2ja(self, arr: int): |
||||
|
""" |
||||
|
python字节数组转java字节数组 |
||||
|
:return: |
||||
|
""" |
||||
|
while arr >= 256: |
||||
|
arr = arr - 256 |
||||
|
return arr |
||||
|
|
||||
|
|
||||
|
if __name__ == '__main__': |
||||
|
# UUID = "ENYnDJO5CNGnCJC5DzcyBWHtEJK4ENcyDJu3EG==" |
||||
|
v = ModifiedBase64() |
||||
|
# a = v.m23209eC(UUID) |
||||
|
# print(a) |
||||
|
|
||||
|
text = '5ZIG5Ya26AQX6YQJ5YsY6SML5bsS' |
||||
|
print(v.m23209eC(text)) |
||||
|
|
||||
|
text = '唐冶街道刘老师' |
||||
|
print(v.m23207r(text)) |
@ -0,0 +1,51 @@ |
|||||
|
import base64 |
||||
|
import hashlib |
||||
|
|
||||
|
|
||||
|
def getSign(params): |
||||
|
# sv传120 |
||||
|
key = [55, 146, 68, 104, 165, 61, 204, 127, 187, 15, 217, 136, 238, 154, 233, 90] |
||||
|
arg0 = [56, 48, 51, 48, 54, 102, 52, 51, 55, 48, 98, 51, 57, 102, 100, 53, 54, 51, 48, 97, 100, 48, 53, 50, 57, 102, |
||||
|
55, 55, 97, 100, 98, 54] |
||||
|
|
||||
|
sign = "functionId=" + params.get("functionId") + "&body=" + params.get("body") + "&uuid=" + params.get("uuid") \ |
||||
|
+ "&client=" + params.get("client") + "&clientVersion=" + params.get("clientVersion") + "&st=" + str( |
||||
|
params.get("st")) \ |
||||
|
+ "&sv=" + str(params.get("sv")) |
||||
|
arg2 = bytearray(sign, 'utf-8') |
||||
|
# print([x for x in arg2]) |
||||
|
ss = [None] * len(arg2) |
||||
|
for i in range(len(arg2)): |
||||
|
R0 = arg2[i] |
||||
|
R2 = key[i & 15] |
||||
|
R4 = arg0[i & 7] |
||||
|
R0 = ((R2 ^ R0) ^ R4) + R2 |
||||
|
R2 = (R2 ^ R0) |
||||
|
R1 = arg0[i & 7] |
||||
|
R2 = (R2 ^ R1) |
||||
|
# print(R2) |
||||
|
ss[i] = R2 |
||||
|
m = hashlib.md5() |
||||
|
m.update(base64.b64encode(bytes(i % 256 for i in ss))) |
||||
|
return str(params.get("st")), m.hexdigest(), str(params.get("sv")) |
||||
|
# return "st=" + str(params.get("st")) + "&sign=" + m.hexdigest() + "&sv=" + str(params.get("sv")) |
||||
|
|
||||
|
|
||||
|
def generateSign(): |
||||
|
params = { |
||||
|
"st": 1648992407201, # 毫秒级时间戳 |
||||
|
"sv": "120", |
||||
|
"functionId": 'serverConfig', |
||||
|
"uuid": '947934e94e0cb9e4', |
||||
|
"client": "android", |
||||
|
"clientVersion": '10.4.6', |
||||
|
# "body": '{"to":"https://plogin.m.jd.com/jd-mlogin/static/html/appjmp_blank.html"}' |
||||
|
"body": '{}' |
||||
|
} |
||||
|
# return getSign(params) |
||||
|
print(getSign(params)) |
||||
|
# print("正确结果:st=1648992407201&sign=474c50af52257126ae65700b825bdf4c&sv=120") |
||||
|
|
||||
|
|
||||
|
if __name__ == '__main__': |
||||
|
generateSign() |
@ -0,0 +1,31 @@ |
|||||
|
import logging |
||||
|
import logging.handlers |
||||
|
import os |
||||
|
|
||||
|
''' |
||||
|
os.getcwd()代表py执行目录 |
||||
|
日志模块 |
||||
|
''' |
||||
|
|
||||
|
# 创建log文件夹 |
||||
|
new_path = os.path.join(os.getcwd(), 'log') |
||||
|
if not os.path.exists(new_path): |
||||
|
os.makedirs(new_path) |
||||
|
|
||||
|
LOG_FILENAME = 'log/jd.log' |
||||
|
logger = logging.getLogger() |
||||
|
|
||||
|
def set_logger(): |
||||
|
if not logger.handlers: |
||||
|
logger.setLevel(logging.INFO) |
||||
|
formatter = logging.Formatter('%(asctime)s - %(levelname)s: %(message)s') |
||||
|
console_handler = logging.StreamHandler() |
||||
|
console_handler.setFormatter(formatter) |
||||
|
logger.addHandler(console_handler) |
||||
|
file_handler = logging.handlers.RotatingFileHandler( |
||||
|
LOG_FILENAME, maxBytes=5*1024*1024, backupCount=5, encoding="utf-8") |
||||
|
file_handler.setFormatter(formatter) |
||||
|
logger.addHandler(file_handler) |
||||
|
|
||||
|
|
||||
|
set_logger() |
@ -0,0 +1,163 @@ |
|||||
|
import hashlib |
||||
|
import platform |
||||
|
import random |
||||
|
import socket |
||||
|
from datetime import datetime |
||||
|
import sys |
||||
|
import os |
||||
|
|
||||
|
from http.cookies import SimpleCookie |
||||
|
|
||||
|
import json |
||||
|
import re |
||||
|
|
||||
|
from tools.ModifiedBase64 import ModifiedBase64 |
||||
|
|
||||
|
|
||||
|
def text_to_json(text, regex): |
||||
|
pattern = re.compile(regex) |
||||
|
text_list = re.findall(pattern, text) |
||||
|
_json = json.loads(text_list[0]) |
||||
|
return _json |
||||
|
|
||||
|
|
||||
|
def remove_unused_symbol(text): |
||||
|
return text.replace('\n', '').replace('\r', '').replace('\t', '') |
||||
|
|
||||
|
|
||||
|
def remove_redundant_comma(text): |
||||
|
""" |
||||
|
移除json多余逗号,避免json.loads报错 |
||||
|
""" |
||||
|
rex = r"""(?<=[}\]"'])\s*,\s*(?!\s*[{["'])""" |
||||
|
return re.sub(rex, "", text, 0) |
||||
|
|
||||
|
|
||||
|
def resource_path(relative_path): |
||||
|
if getattr(sys, 'frozen', False): |
||||
|
base_path = sys._MEIPASS |
||||
|
else: |
||||
|
base_path = os.path.abspath("../..") |
||||
|
return os.path.join(base_path, relative_path) |
||||
|
|
||||
|
|
||||
|
def export_file_name(): |
||||
|
return "ck-export-" + datetime.now().strftime('%Y%m%d%H%M%S') + ".txt" |
||||
|
|
||||
|
|
||||
|
def desktop_path(): |
||||
|
if platform.system() == 'Windows': |
||||
|
return r"C:\Users\Administrator\Desktop" |
||||
|
else: |
||||
|
return "/Users/xiaoqingsong/Desktop" |
||||
|
|
||||
|
|
||||
|
def is_json(text): |
||||
|
if text is None: |
||||
|
return False |
||||
|
try: |
||||
|
json.loads(text) |
||||
|
except ValueError: |
||||
|
return False |
||||
|
return True |
||||
|
|
||||
|
|
||||
|
def getTimeStamp(time): |
||||
|
""" |
||||
|
:param time: 形如 2021-01-20 10:10:20.120 |
||||
|
:return: |
||||
|
""" |
||||
|
ts = datetime.timestamp(datetime.strptime(time, '%Y-%m-%d %H:%M:%S.%f')) |
||||
|
return int(ts * 1000) |
||||
|
|
||||
|
|
||||
|
def getTimeStamp(time, format): |
||||
|
""" |
||||
|
:param format: %Y-%m-%d %H:%M:%S |
||||
|
:param time: 形如 2021-01-20 10:10:20 |
||||
|
:return: |
||||
|
""" |
||||
|
ts = datetime.timestamp(datetime.strptime(time, format)) |
||||
|
return int(ts * 1000) |
||||
|
|
||||
|
|
||||
|
def getNowTime(): |
||||
|
return datetime.now().strftime('%Y-%m-%d %H:%M:%S.%f')[:-7] |
||||
|
|
||||
|
|
||||
|
def getCookieFromStr(rawStr): |
||||
|
cookie = SimpleCookie() |
||||
|
cookie.load(rawStr) |
||||
|
# Even though SimpleCookie is dictionary-like, it internally uses a Morsel object |
||||
|
# which is incompatible with requests. Manually construct a dictionary instead. |
||||
|
cookies = {} |
||||
|
for key, morsel in cookie.items(): |
||||
|
cookies[key] = morsel.value |
||||
|
return cookies |
||||
|
|
||||
|
|
||||
|
def get_random_number_str(length): |
||||
|
""" |
||||
|
生成随机数字字符串 |
||||
|
:param length: 字符串长度 |
||||
|
:return: |
||||
|
""" |
||||
|
num_str = ''.join(str(random.choice(range(10))) for _ in range(length)) |
||||
|
return num_str |
||||
|
|
||||
|
|
||||
|
def randomUUID(): |
||||
|
random_number = get_random_number_str(15) |
||||
|
random_str = hashlib.md5(random_number.encode('utf-8')).hexdigest()[:12] |
||||
|
return random_number + "-" + random_str |
||||
|
|
||||
|
|
||||
|
def get_host_ip(): |
||||
|
try: |
||||
|
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) |
||||
|
s.connect(('8.8.8.8', 80)) |
||||
|
ip = s.getsockname()[0] |
||||
|
finally: |
||||
|
s.close() |
||||
|
|
||||
|
return ip |
||||
|
|
||||
|
|
||||
|
def mb_encrypt(str): |
||||
|
v = ModifiedBase64() |
||||
|
return v.m23207r(str) |
||||
|
|
||||
|
|
||||
|
def get_ep(ts, uuid): |
||||
|
area = '13_1000_40488_54435' |
||||
|
d_model = 'PDNM00' |
||||
|
wifiBssid = 'unknown' |
||||
|
osVersion = '11' |
||||
|
d_brand = 'OPPO' |
||||
|
screen = '2161*1080' |
||||
|
uuid = uuid |
||||
|
aid = uuid |
||||
|
openudid = uuid |
||||
|
hdid = '' |
||||
|
|
||||
|
ep = { |
||||
|
'hdid': mb_encrypt(hdid), |
||||
|
'ts': ts, |
||||
|
'ridx': -1, |
||||
|
'cipher': { |
||||
|
'area': mb_encrypt(area), |
||||
|
'd_model': mb_encrypt(d_model), |
||||
|
'wifiBssid': mb_encrypt(wifiBssid), |
||||
|
'osVersion': mb_encrypt(osVersion), |
||||
|
'd_brand': mb_encrypt(d_brand), |
||||
|
'screen': mb_encrypt(screen), |
||||
|
'uuid': mb_encrypt(uuid), |
||||
|
'aid': mb_encrypt(aid), |
||||
|
'openudid': mb_encrypt(openudid), |
||||
|
}, |
||||
|
'ciphertype': 5, |
||||
|
'version': '1.2.0', |
||||
|
'appname': 'com.jingdong.app.mall', |
||||
|
} |
||||
|
|
||||
|
return ep |
Loading…
Reference in new issue