AJiaJiShu commited on
Commit
c79e1fa
·
verified ·
1 Parent(s): a266d9e

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +516 -0
app.py ADDED
@@ -0,0 +1,516 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # coding:utf-8
2
+
3
+ """
4
+ PikPak登录接口自动过滑块验证码-AAA
5
+ """
6
+ from quart import Quart, request, jsonify
7
+ from quart_cors import route_cors
8
+ import asyncio
9
+ from hypercorn.config import Config
10
+ from hypercorn.asyncio import serve
11
+ from multiprocessing import Pool
12
+ from functools import partial
13
+ from tqdm import trange
14
+ import numpy as np
15
+ import requests
16
+ import hashlib
17
+ import random
18
+ import json
19
+ import uuid
20
+ import time
21
+ import cv2
22
+
23
+ # 滑块数据加密
24
+ def r(e, t):
25
+ n = t - 1
26
+ if n < 0:
27
+ n = 0
28
+ r = e[n]
29
+ u = r["row"] // 2 + 1
30
+ c = r["column"] // 2 + 1
31
+ f = r["matrix"][u][c]
32
+ l = t + 1
33
+ if l >= len(e):
34
+ l = t
35
+ d = e[l]
36
+ p = l % d["row"]
37
+ h = l % d["column"]
38
+ g = d["matrix"][p][h]
39
+ y = e[t]
40
+ m = 3 % y["row"]
41
+ v = 7 % y["column"]
42
+ w = y["matrix"][m][v]
43
+ b = i(f) + o(w)
44
+ x = i(w) - o(f)
45
+ return [s(a(i(f), o(f))), s(a(i(g), o(g))), s(a(i(w), o(w))), s(a(b, x))]
46
+
47
+
48
+ def i(e):
49
+ return int(e.split(",")[0])
50
+
51
+
52
+ def o(e):
53
+ return int(e.split(",")[1])
54
+
55
+
56
+ def a(e, t):
57
+ return str(e) + "^⁣^" + str(t)
58
+
59
+
60
+ def s(e):
61
+ t = 0
62
+ n = len(e)
63
+ for r in range(n):
64
+ t = u(31 * t + ord(e[r]))
65
+ return t
66
+
67
+
68
+ def u(e):
69
+ t = -2147483648
70
+ n = 2147483647
71
+ if e > n:
72
+ return t + (e - n) % (n - t + 1) - 1
73
+ if e < t:
74
+ return n - (t - e) % (n - t + 1) + 1
75
+ return e
76
+
77
+
78
+ def c(e, t):
79
+ return s(e + "⁣" + str(t))
80
+
81
+
82
+ def img_jj(e, t, n):
83
+ return {"ca": r(e, t), "f": c(n, t)}
84
+
85
+
86
+ # md5加密字符串
87
+ def get_hash(str):
88
+ return hashlib.md5(str.encode()).hexdigest()
89
+
90
+
91
+ def get_change_ip():
92
+ m = random.randint(0, 255)
93
+ n = random.randint(0, 255)
94
+ x = random.randint(0, 255)
95
+ y = random.randint(0, 255)
96
+ randomIP = str(m) + '.' + str(n) + '.' + str(x) + '.' + str(y)
97
+ return randomIP
98
+
99
+
100
+ # 创建随机UA
101
+ def get_user_agent():
102
+ tmp1 = random.randrange(90, 120)
103
+ tmp2 = random.randrange(5200, 5500)
104
+ tmp3 = random.randrange(90, 180)
105
+ tmp_version = str(tmp1) + ".0." + str(tmp2) + "." + str(tmp3)
106
+ ua = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/' + tmp_version + ' Safari/537.36'
107
+ print(ua)
108
+ return ua
109
+
110
+
111
+ # 设置请求头基本信息
112
+ basicRequestHeaders_1 = {
113
+ "Accept-Language": "zh",
114
+ "Content-Type": "application/json; charset=utf-8",
115
+ "Host": "user.mypikpak.com",
116
+ "Connection": "Keep-Alive",
117
+ "Accept-Encoding": "gzip",
118
+ "content-type": "application/json"
119
+ }
120
+
121
+ def get_image_d(pid, device_id, f, change_ip):
122
+ url = "https://pik-d.bilivo.top/"
123
+ payload = {
124
+ "pid": pid,
125
+ "device_id": device_id,
126
+ "f": f
127
+ }
128
+ headers = {
129
+ 'content-type': 'application/json',
130
+ 'X-Forwarded-For': str(change_ip)
131
+ }
132
+ response = requests.request("POST", url, json=payload, headers=headers)
133
+ response_data = response.json()
134
+ # print(f"d:{response_data['d']}")
135
+ return response_data['d']
136
+
137
+
138
+ # 安全验证-登录
139
+ def init(client_id, device_id, User_Agent, mail, change_ip):
140
+ url = f"https://user.mypikpak.net/v1/shield/captcha/init"
141
+ payload = {
142
+ "action": "POST:/v1/auth/signin",
143
+ "captcha_token": '',
144
+ "client_id": client_id,
145
+ "device_id": device_id,
146
+ "meta": {
147
+ "email": mail
148
+ },
149
+ }
150
+ headers = {
151
+ "x-client-id": "YUMx5nI8ZU8Ap8pm",
152
+ "X-Device-Id": device_id,
153
+ "User-Agent": User_Agent,
154
+ 'X-Forwarded-For': str(change_ip)
155
+ }
156
+ headers.update(basicRequestHeaders_1)
157
+ response = requests.request("POST", url, json=payload, headers=headers)
158
+ return json.loads(response.text)
159
+
160
+
161
+ def get_image(xid, change_ip):
162
+ url = "http://user.mypikpak.com/pzzl/gen"
163
+ header = {'X-Forwarded-For': str(change_ip)}
164
+ params = {
165
+ "deviceid": xid,
166
+ "traceid": ""
167
+ }
168
+ response = requests.get(url, params=params)
169
+ imgs_json = response.json()
170
+ frames = imgs_json["frames"]
171
+ pid = imgs_json['pid']
172
+ traceid = imgs_json['traceid']
173
+ result = {"frames": frames}
174
+ SELECT_ID = pass_verify(xid, pid, traceid, result,)
175
+ print('滑块ID:' + str(SELECT_ID))
176
+ json_data = img_jj(frames, int(SELECT_ID), pid)
177
+ f = json_data['f']
178
+ npac = json_data['ca']
179
+ d = get_image_d(pid, xid, f, change_ip)
180
+ params = {
181
+ 'pid': pid,
182
+ 'deviceid': xid,
183
+ 'traceid': traceid,
184
+ 'f': f,
185
+ 'n': npac[0],
186
+ 'p': npac[1],
187
+ 'a': npac[2],
188
+ 'd': d,
189
+ 'c': npac[3]
190
+ }
191
+ response1 = requests.get(f"http://user.mypikpak.com/pzzl/verify", params=params, headers=header)
192
+ response_data = response1.json()
193
+ result = {'pid': pid, 'traceid': traceid, 'response_data': response_data}
194
+ return result
195
+
196
+
197
+ def sign_in(device_id, username, password, client_id, captcha_token, change_ip):
198
+ url = "https://user.pikpak.me/v1/auth/signin"
199
+
200
+ headers = {
201
+ "X-Captcha-Token": captcha_token,
202
+ # "X-Device-ID": device_id,
203
+ # "x-client-id": client_id,
204
+ 'X-Forwarded-For': str(change_ip)
205
+ }
206
+
207
+ payload = {
208
+ "username": username,
209
+ "password": password,
210
+ "client_id": client_id
211
+ }
212
+
213
+ response = requests.post(url, headers=headers, json=payload)
214
+
215
+ if response.status_code == 200:
216
+ return response.json()
217
+ else:
218
+ return {"error": f"Request failed with status code {response.status_code}"}
219
+
220
+ # ---------------滑块验证---------------
221
+ # 定义一个函数,用于图像拼接
222
+ def image_assemble(sum_rows, sum_cols, channels, part_num):
223
+ # 初始化一个全零的3维矩阵,用于存储拼接后的图像
224
+ final_matrix = np.zeros((sum_rows, sum_cols, channels), np.uint8)
225
+
226
+ # 第一排
227
+ final_matrix[0:75, 0:150] = part_num[0]
228
+ final_matrix[0:75, 150:300] = part_num[1]
229
+ final_matrix[0:75, 300:450] = part_num[2]
230
+ final_matrix[0:75, 450:600] = part_num[3]
231
+
232
+ # 第二排
233
+ final_matrix[75:150, 0:150] = part_num[4]
234
+ final_matrix[75:150, 150:300] = part_num[5]
235
+ final_matrix[75:150, 300:450] = part_num[6]
236
+ final_matrix[75:150, 450:600] = part_num[7]
237
+
238
+ # 第三排
239
+ final_matrix[150:225, 0:150] = part_num[8]
240
+ final_matrix[150:225, 150:300] = part_num[9]
241
+ final_matrix[150:225, 300:450] = part_num[10]
242
+ final_matrix[150:225, 450:600] = part_num[11]
243
+
244
+ # 第四排
245
+ final_matrix[225:300, 0:150] = part_num[12]
246
+ final_matrix[225:300, 150:300] = part_num[13]
247
+ final_matrix[225:300, 300:450] = part_num[14]
248
+ final_matrix[225:300, 450:600] = part_num[15]
249
+ # 返回拼接后的图像
250
+ return final_matrix
251
+
252
+
253
+ def get_img(deviceid, pid, traceid):
254
+ url = 'http://user.mypikpak.com/pzzl/image?deviceid=' + deviceid + '&pid=' + pid + '&traceid=' + traceid
255
+ response = requests.get(url)
256
+ return response.content
257
+
258
+
259
+ def getSize(p):
260
+ sum_rows = p.shape[0]
261
+ sum_cols = p.shape[1]
262
+ channels = p.shape[2]
263
+ return sum_rows, sum_cols, channels
264
+
265
+
266
+ def pass_verify(deviceid, pid, traceid, result):
267
+ pool = Pool(10)
268
+ try:
269
+ # 获取验证码图片
270
+ img = get_img(deviceid, pid, traceid)
271
+ # 获取图片大小
272
+ start_time = time.time()
273
+ img_re = cv2.imdecode(np.frombuffer(img, np.uint8), cv2.IMREAD_COLOR)
274
+ finded = False
275
+ sum_rows, sum_cols, channels = getSize(img_re)
276
+ except Exception as e:
277
+ print(e)
278
+ else:
279
+ # 分配进程
280
+ data_list = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]
281
+ start_pass_verify_re = partial(start_pass_verify, sum_rows)
282
+ start_pass_verify_re = partial(start_pass_verify_re, sum_cols)
283
+ start_pass_verify_re = partial(start_pass_verify_re, channels)
284
+ start_pass_verify_re = partial(start_pass_verify_re, img_re)
285
+ start_pass_verify_re = partial(start_pass_verify_re, result)
286
+ len_num = []
287
+ data_i = []
288
+ results = []
289
+ total = trange(len(data_list))
290
+ for data in data_list:
291
+ # 等待任务执行完成
292
+ result = pool.apply_async(start_pass_verify_re, args=(data,), callback=lambda _: total.update(1),)
293
+ data_i.append(data)
294
+ results.append(result)
295
+ pool.close()
296
+ pool.join()
297
+ for data in data_i:
298
+ len_num.append(results[data].get())
299
+ print(len_num)
300
+ for data, line in enumerate(len_num):
301
+ if line is None:
302
+ num = data
303
+ else:
304
+ if data == 0:
305
+ num = 0
306
+ lines = line
307
+ if lines <= line:
308
+ finded = True
309
+ elif lines > line:
310
+ lines = line
311
+ num = data
312
+ data += 1
313
+ print(f'滑块识别时间{time.time() - start_time}')
314
+ print('测试次数', data, '最终状态', finded)
315
+ return num
316
+
317
+
318
+ def start_pass_verify(sum_rows, sum_cols, channels, img, result, i):
319
+ # 获取结果中的frames部分
320
+ part_1 = result["frames"][i]['matrix'][0]
321
+ part_2 = result["frames"][i]['matrix'][1]
322
+ part_3 = result["frames"][i]['matrix'][2]
323
+ part_4 = result["frames"][i]['matrix'][3]
324
+ # 将四个部分合并
325
+ part = []
326
+ part.extend(part_1)
327
+ part.extend(part_2)
328
+ part.extend(part_3)
329
+ part.extend(part_4)
330
+ # 将合并后的部分重新组装
331
+ start_time = time.time()
332
+ part_num = re_image_assemble(part, img)
333
+ # 获取重新组装后的图片
334
+ part_num = get_reimage(part_num)
335
+ # 将重新组装后的图片按照sum_rows和sum_cols进行组装
336
+ f = image_assemble(sum_rows, sum_cols, channels, part_num)
337
+ # 将组装后的图片转换为灰度图
338
+ gray = cv2.cvtColor(f, cv2.COLOR_BGR2GRAY)
339
+ # 对灰度图进行边缘检测
340
+ edges = cv2.Canny(gray, 100, 200, apertureSize=3)
341
+ # 对边缘检测后的图片进行霍夫变换
342
+ # lines = cv2.HoughLinesP(edges, 0.001, np.pi / 180, 1, minLineLength=0, maxLineGap=0)
343
+ lsd = cv2.createLineSegmentDetector(0, scale=3.0, sigma_scale=0.6, quant=2.0, ang_th=90,)
344
+ # 执行检测结果
345
+ lines = lsd.detect(edges)[0]
346
+ # 返回线段数量
347
+ return len(lines)
348
+
349
+
350
+ def re_image_assemble(part, img):
351
+ # 获取图片的每一部分
352
+ part1 = img[0:75, 0:150]
353
+ part2 = img[0:75, 150:300]
354
+ part3 = img[0:75, 300:450]
355
+ part4 = img[0:75, 450:600]
356
+ # 第二排
357
+ part5 = img[75:150, 0:150]
358
+ part6 = img[75:150, 150:300]
359
+ part7 = img[75:150, 300:450]
360
+ part8 = img[75:150, 450:600]
361
+ # 第三排
362
+ part9 = img[150:225, 0:150]
363
+ part10 = img[150:225, 150:300]
364
+ part11 = img[150:225, 300:450]
365
+ part12 = img[150:225, 450:600]
366
+ # 第四排
367
+ part13 = img[225:300, 0:150]
368
+ part14 = img[225:300, 150:300]
369
+ part15 = img[225:300, 300:450]
370
+ part16 = img[225:300, 450:600]
371
+ part_nu = []
372
+ for i, j in enumerate(part):
373
+ if j == '0,0':
374
+ part_nu.append(part1)
375
+ if j == '0,1':
376
+ part_nu.append(part5)
377
+ if j == '0,2':
378
+ part_nu.append(part9)
379
+ if j == '0,3':
380
+ part_nu.append(part13)
381
+ if j == '1,0':
382
+ part_nu.append(part2)
383
+ if j == '1,1':
384
+ part_nu.append(part6)
385
+ if j == '1,2':
386
+ part_nu.append(part10)
387
+ if j == '1,3':
388
+ part_nu.append(part14)
389
+ if j == '2,0':
390
+ part_nu.append(part3)
391
+ if j == '2,1':
392
+ part_nu.append(part7)
393
+ if j == '2,2':
394
+ part_nu.append(part11)
395
+ if j == '2,3':
396
+ part_nu.append(part15)
397
+ if j == '3,0':
398
+ part_nu.append(part4)
399
+ if j == '3,1':
400
+ part_nu.append(part8)
401
+ if j == '3,2':
402
+ part_nu.append(part12)
403
+ if j == '3,3':
404
+ part_nu.append(part16)
405
+ return part_nu
406
+
407
+ # 定义一个函数,用于获取处理图像
408
+ def get_reimage(images):
409
+ # 定义一个空字典,用于存储裁剪后的图像
410
+ cropped_img = {}
411
+ # 遍历images中的每一张图像
412
+ for i in range(16):
413
+ # 对图像进行裁剪
414
+ re_num = corp_image(images[i])
415
+ # 将裁剪后的图像resize为150x75的大小
416
+ cropped_img[i] = cv2.resize(re_num, (150, 75))
417
+ # 返回裁剪后的图像字典
418
+ return cropped_img
419
+
420
+ # 定义一个函数,用于处理图像
421
+ def corp_image(img):
422
+ # 将图像转换为灰度图像
423
+ img2 = img.sum(axis=2)
424
+ # 获取图像的行数和列数
425
+ (row, col) = img2.shape
426
+ # 初始化行和列的上下界
427
+ row_top = 0
428
+ raw_down = 0
429
+ col_top = 0
430
+ col_down = 0
431
+ # 遍历行,找到行上下界
432
+ for r in range(0, row):
433
+ if img2.sum(axis=1)[r] < 740 * col:
434
+ row_top = r
435
+ break
436
+
437
+ for r in range(row - 1, 0, -1):
438
+ if img2.sum(axis=1)[r] < 740 * col:
439
+ raw_down = r
440
+ break
441
+
442
+ # 遍历列,找到列上下界
443
+ for c in range(0, col):
444
+ if img2.sum(axis=0)[c] < 740 * row:
445
+ col_top = c
446
+ break
447
+
448
+ for c in range(col - 1, 0, -1):
449
+ if img2.sum(axis=0)[c] < 740 * row:
450
+ col_down = c
451
+ break
452
+
453
+ # 裁剪图像,并返回新的图像
454
+ new_img = img[row_top:raw_down + 1, col_top:col_down + 1, 0:3]
455
+ return new_img
456
+
457
+ def get_new_token(result, xid, captcha, change_ip):
458
+ traceid = result['traceid']
459
+ pid = result['pid']
460
+ header = {'X-Forwarded-For': str(change_ip)}
461
+ response2 = requests.get(
462
+ f"http://user.mypikpak.com/credit/v1/report?deviceid={xid}&captcha_token={captcha}&type"
463
+ f"=pzzlSlider&result=0&data={pid}&traceid={traceid}", headers=header)
464
+ response_data = response2.json()
465
+ print('获取验证TOKEN中......')
466
+ return response_data
467
+
468
+ # ---------------滑块验证---------------
469
+ app = Quart(__name__)
470
+
471
+
472
+ @app.route('/', methods=['GET'])
473
+ @route_cors(allow_origin='*')
474
+ async def home():
475
+ data = json.dumps({"msg": "用于PikPak登录获取 AccessToken接口-作者:AAA",
476
+ "data": "https://github.com/LiJunYi2"}, ensure_ascii=False)
477
+ return jsonify(data), 200
478
+
479
+
480
+ @app.route('/login', methods=['POST'])
481
+ @route_cors(allow_origin='*')
482
+ async def login():
483
+ data = request.get_json()
484
+ if not data:
485
+ return jsonify({"error": "没有指定参数"}), 400
486
+ email = data.get('userName')
487
+ password = data.get('passWord')
488
+ try:
489
+ change_ip = get_change_ip()
490
+ client_id1 = "YNxT9w7GMdWvEOKa"
491
+ device_id = str(uuid.uuid4()).replace("-", "")
492
+ user_agent = get_user_agent()
493
+ action_init = init(client_id1, device_id, user_agent, email, change_ip)
494
+ captcha_token = action_init["captcha_token"]
495
+ while True:
496
+ img_info = get_image(device_id, change_ip)
497
+ if img_info['response_data']['result'] == 'accept':
498
+ print('验证通过!!!')
499
+ break
500
+ token_data = get_new_token(img_info, device_id, captcha_token, change_ip)
501
+ login_data = sign_in(device_id, email, password, client_id1, token_data['captcha_token'], change_ip)
502
+ return jsonify({"code": 200, "data": login_data, "msg": 'success'}), 200
503
+ except Exception as e:
504
+ print(e)
505
+ return jsonify({"code": 500, "data": {}, "msg": '登录失败'}), 500
506
+
507
+
508
+ config = Config()
509
+ config.bind = ["0.0.0.0:8090"]
510
+
511
+
512
+ if __name__ == '__main__':
513
+ import asyncio
514
+ asyncio.run(serve(app, config))
515
+
516
+