-
Notifications
You must be signed in to change notification settings - Fork 198
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #83 from Amorter/main
自动验证功能
- Loading branch information
Showing
8 changed files
with
9,369 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,136 @@ | ||
import requests | ||
import json | ||
from typing import Tuple | ||
import time | ||
|
||
class Slide: | ||
def register(self) -> Tuple[str, str]: | ||
url = "http://127.0.0.1:5000/pc-geetest/register?t=" + str(int(time.time() * 1000)) | ||
# url = "https://www.geetest.com/demo/gt/register-slide?t=" + str(int(time.time() * 1000)) | ||
res = requests.get(url=url).json() | ||
print(res) | ||
return (res['challenge'], res['gt']) | ||
|
||
def get_c_s(self, challenge: str, gt: str, w: str) -> Tuple[list, str]: | ||
url = "https://api.geetest.com/get.php" | ||
# url = "https://apiv6.geetest.com/get.php" | ||
res = requests.get(url=url, params={ | ||
"gt": gt, | ||
"challenge": challenge, | ||
"lang": "zh-cn", | ||
"pt": 0, | ||
"client_type": "web", | ||
"w": w, | ||
}).text | ||
res = json.loads(res.strip('()'))['data'] | ||
# print(res) | ||
return (res['c'], res['s']) | ||
|
||
def get_type(self, challenge: str, gt: str, w: str): | ||
url = "http://api.geevisit.com/ajax.php" | ||
res = requests.get(url=url, params={ | ||
"gt": gt, | ||
"challenge": challenge, | ||
"w": w | ||
}) | ||
def get_new_c_s_challenge_bg_slice(self, challenge: str, gt: str,) -> Tuple[str, str, str, str, str]: | ||
url = "http://api.geevisit.com/get.php" | ||
res = requests.get(url=url, params={ | ||
"gt": gt, | ||
"challenge": challenge, | ||
"is_next": "true", | ||
"offline": "false", | ||
"type": "slide3", | ||
"isPC": "true", | ||
"product": "embed", | ||
"autoReset": "true", | ||
"api_server": "api.geevisit.com", | ||
"protocol": "http://", | ||
"width": "100%", | ||
"callback": "geetest_1715753608245", | ||
}).text | ||
res = res.strip('geetest_1715753608245') | ||
res = res.strip('()') | ||
res = json.loads(res) | ||
print(res) | ||
return (res['c'],res['s'],res['challenge'], | ||
'https://' + res['static_servers'][0] + res['bg'], | ||
'https://' + res['static_servers'][0] + res['slice']) | ||
|
||
def ajax(self, challenge: str, gt: str, w: str): | ||
url = "http://api.geevisit.com/ajax.php" | ||
res = requests.get(url=url, params={ | ||
"gt": gt, | ||
"challenge": challenge, | ||
"w": w, | ||
}).text | ||
res = res.strip('()') | ||
res = json.loads(res) | ||
print(res) | ||
return res | ||
|
||
class Click: | ||
def register(self) -> Tuple[str, str]: | ||
url = "https://account.geetest.com/api/captchademo?captcha_type=click" | ||
res = requests.get(url=url).json() | ||
res = res["data"] | ||
print(res) | ||
return (res['challenge'], res['gt']) | ||
|
||
def get_c_s(self, challenge: str, gt: str, w: str) -> Tuple[list, str]: | ||
url = "https://api.geetest.com/get.php" | ||
# url = "https://apiv6.geetest.com/get.php" | ||
res = requests.get(url=url, params={ | ||
"gt": gt, | ||
"challenge": challenge, | ||
"lang": "zh-cn", | ||
"pt": 0, | ||
"client_type": "web", | ||
"w": w, | ||
}).text | ||
res = json.loads(res.strip('()'))['data'] | ||
# print(res) | ||
return (res['c'], res['s']) | ||
|
||
def get_type(self, challenge: str, gt: str, w: str): | ||
url = "http://api.geevisit.com/ajax.php" | ||
res = requests.get(url=url, params={ | ||
"gt": gt, | ||
"challenge": challenge, | ||
"w": w | ||
}) | ||
def get_new_c_s_pic(self, challenge: str, gt: str,) -> Tuple[str, str, str]: | ||
url = "http://api.geevisit.com/get.php" | ||
res = requests.get(url=url, params={ | ||
"gt": gt, | ||
"challenge": challenge, | ||
"is_next": "true", | ||
"offline": "false", | ||
"type": "slide3", | ||
"isPC": "true", | ||
"product": "embed", | ||
"autoReset": "true", | ||
"api_server": "api.geevisit.com", | ||
"protocol": "http://", | ||
"width": "100%", | ||
"callback": "geetest_1715753608245", | ||
}).text | ||
res = res.strip('geetest_1715753608245') | ||
res = res.strip('()') | ||
res = json.loads(res) | ||
res = res["data"] | ||
print(res) | ||
return (res['c'],res['s'], | ||
'https://' + res['static_servers'][0] + res['pic'],) | ||
|
||
def ajax(self, challenge: str, gt: str, w: str): | ||
url = "http://api.geevisit.com/ajax.php" | ||
res = requests.get(url=url, params={ | ||
"gt": gt, | ||
"challenge": challenge, | ||
"w": w, | ||
}).text | ||
res = res.strip('()') | ||
res = json.loads(res) | ||
print(res) | ||
return res |
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
# -*- coding: utf-8 -*- | ||
import io | ||
from pathlib import Path | ||
import requests | ||
from PIL import Image | ||
import ddddocr | ||
from typing import Tuple | ||
|
||
def slice_img(img) -> Tuple[Image.Image, Image.Image]: | ||
if isinstance(img, (str, Path)): | ||
_img = Image.open(img) | ||
elif isinstance(img, bytes): | ||
_img = Image.open(io.BytesIO(img)) | ||
else: | ||
raise ValueError(f'输入图片类型错误, 必须是<type str>/<type Path>/<type bytes>: {type(img)}') | ||
background_img = _img.crop((0, 0, 344, 344)) | ||
text_img = _img.crop((0, 345, 116, 384)) | ||
return(background_img, text_img) | ||
|
||
class Click3: | ||
def __init__(self, ocr: ddddocr.DdddOcr = ddddocr.DdddOcr(show_ad=False, beta=True), | ||
det: ddddocr.DdddOcr = ddddocr.DdddOcr(show_ad=False, det=True)): | ||
self.ocr = ocr | ||
self.det = det | ||
|
||
def calculated_position(self, img_url): | ||
img = requests.get(img_url).content | ||
|
||
(background_img, text_img) = slice_img(img) | ||
text = self.ocr.classification(text_img) | ||
print(text) | ||
background_bytes = io.BytesIO() | ||
background_img.save(background_bytes, format='PNG') | ||
background_bytes.seek(0) | ||
bboxes = self.det.detection(background_bytes.read()) | ||
texts = list() | ||
for bbox in bboxes: | ||
(x1, y1, x2, y2) = bbox | ||
img = background_img.crop((x1, y1, x2, y2)) | ||
this_text = self.ocr.classification(img) | ||
texts.append(this_text) | ||
print(texts) | ||
res = list() | ||
no_finds = list() | ||
is_find = [False] * texts.__len__() | ||
for c in text: | ||
try: | ||
index = texts.index(c) | ||
except: | ||
no_finds.append(c) | ||
continue | ||
is_find[index] = True | ||
position = str(round((bboxes[index][0] + bboxes[index][2]) / 2 / 333.375 * 100 * 100)) + '_' + str(round((bboxes[index][1] + bboxes[index][3]) / 2 / 333.375 * 100 * 100)) | ||
res.append(position) | ||
for c in no_finds: | ||
for i in range(len(is_find)): | ||
if not is_find[i]: | ||
is_find[i] = True | ||
position = str(round((bboxes[i][0] + bboxes[i][2]) / 2 / 333.375 * 100 * 100)) + '_' + str(round((bboxes[i][1] + bboxes[i][3]) / 2 / 333.375 * 100 * 100)) | ||
res.append(position) | ||
break | ||
print(res) | ||
return ','.join(res) | ||
|
||
if __name__ == '__main__': | ||
click = Click3() | ||
img = "https://static.geetest.com/captcha_v3/batch/v3/72556/2024-06-06T05/word/42a62cb4cafb461d92eee08598c13b95.jpg?challenge=a8a9ae907a766d68f9fed4035aab4929" | ||
print(click.calculated_position(img)) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,81 @@ | ||
from api import Slide, Click | ||
import subprocess | ||
from slide3 import Slide3 | ||
from click3 import Click3 | ||
import time | ||
from ddddocr import DdddOcr | ||
|
||
def main1(): | ||
api = Slide() | ||
slide3 = Slide3() | ||
|
||
cmd0 = "node -e \"require('./rt.js').rt()\"" | ||
print(cmd0) | ||
rt = subprocess.run(cmd0, shell=True, stdout=subprocess.PIPE).stdout.decode('utf-8') | ||
(challenge, gt) = api.register() | ||
|
||
print(challenge) | ||
print(gt) | ||
(c, s) = api.get_c_s(challenge, gt, None) | ||
|
||
api.get_type(challenge, gt, None) | ||
|
||
(c, s, challenge, bg_url, slice_url) = api.get_new_c_s_challenge_bg_slice(challenge, gt) | ||
dis = slide3.calculated_distance(bg_url, slice_url) | ||
cmd3 = "node -e \"require('./slide.js').send(" + str(dis) + ",\'" + gt + "\',\'" + challenge + "\'," + str(c) + ",\'" + s + "\',\'"+ rt + "\')\"" | ||
print(cmd3) | ||
w = subprocess.run(cmd3, shell=True, stdout=subprocess.PIPE).stdout.decode('utf-8') | ||
time.sleep(2) | ||
res = api.ajax(challenge, gt, w) | ||
print(res) | ||
|
||
def main2(): | ||
api = Click() | ||
click3 = Click3() | ||
|
||
cmd0 = "node -e \"require('./rt.js').rt()\"" | ||
print(cmd0) | ||
rt = subprocess.run(cmd0, shell=True, stdout=subprocess.PIPE).stdout.decode('utf-8') | ||
(challenge, gt) = api.register() | ||
|
||
print(challenge) | ||
print(gt) | ||
(c, s) = api.get_c_s(challenge, gt, None) | ||
|
||
api.get_type(challenge, gt, None) | ||
|
||
(c, s, pic) = api.get_new_c_s_pic(challenge, gt) | ||
position = click3.calculated_position(pic) | ||
cmd3 = "node -e \"require('./click.js').send('" + gt + "\',\'" + challenge + "\'," + str(c) + ",\'" + s + "\',\'"+ rt + "\',\'" + position + "\')\"" | ||
print(cmd3) | ||
w = subprocess.run(cmd3, shell=True, stdout=subprocess.PIPE).stdout.decode('utf-8') | ||
time.sleep(2) | ||
res = api.ajax(challenge, gt, w) | ||
print(res) | ||
|
||
def main3(): | ||
api = Click() | ||
click3 = Click3(DdddOcr(show_ad=False, beta=True)) | ||
count = 0 | ||
for i in range(300): | ||
cmd0 = "node -e \"require('./rt.js').rt()\"" | ||
rt = subprocess.run(cmd0, shell=True, stdout=subprocess.PIPE).stdout.decode('utf-8') | ||
(challenge, gt) = api.register() | ||
(c, s) = api.get_c_s(challenge, gt, None) | ||
|
||
api.get_type(challenge, gt, None) | ||
|
||
(c, s, pic) = api.get_new_c_s_pic(challenge, gt) | ||
position = click3.calculated_position(pic) | ||
cmd3 = "node -e \"require('.click.js').send('" + gt + "\',\'" + challenge + "\'," + str(c) + ",\'" + s + "\',\'"+ rt + "\',\'" + position + "\')\"" | ||
w = subprocess.run(cmd3, shell=True, stdout=subprocess.PIPE).stdout.decode('utf-8') | ||
time.sleep(2) | ||
res = api.ajax(challenge, gt, w) | ||
print(res) | ||
if(res['data']['result'] == 'success'): | ||
count+=1 | ||
|
||
print(count/300) | ||
|
||
if __name__ == '__main__': | ||
main3() |
Large diffs are not rendered by default.
Oops, something went wrong.
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,79 @@ | ||
# -*- coding: utf-8 -*- | ||
import io | ||
from pathlib import Path | ||
import requests | ||
from PIL import Image | ||
import ddddocr | ||
|
||
def parse_bg_captcha(img, im_show=False, save_path=None): | ||
""" | ||
滑块乱序背景图还原 | ||
:param img: 图片路径str/图片路径Path对象/图片二进制 | ||
eg: 'assets/bg.webp' | ||
Path('assets/bg.webp') | ||
:param im_show: 是否显示还原结果, <type 'bool'>; default: False | ||
:param save_path: 保存路径, <type 'str'>/<type 'Path'>; default: None | ||
:return: 还原后背景图 RGB图片格式 | ||
""" | ||
if isinstance(img, (str, Path)): | ||
_img = Image.open(img) | ||
elif isinstance(img, bytes): | ||
_img = Image.open(io.BytesIO(img)) | ||
else: | ||
raise ValueError(f'输入图片类型错误, 必须是<type str>/<type Path>/<type bytes>: {type(img)}') | ||
# 图片还原顺序, 定值 | ||
_Ge = [39, 38, 48, 49, 41, 40, 46, 47, 35, 34, 50, 51, 33, 32, 28, 29, 27, 26, 36, 37, 31, 30, 44, 45, 43, | ||
42, 12, 13, 23, 22, 14, 15, 21, 20, 8, 9, 25, 24, 6, 7, 3, 2, 0, 1, 11, 10, 4, 5, 19, 18, 16, 17] | ||
w_sep, h_sep = 10, 80 | ||
|
||
# 还原后的背景图 | ||
new_img = Image.new('RGB', (260, 160)) | ||
|
||
for idx in range(len(_Ge)): | ||
x = _Ge[idx] % 26 * 12 + 1 | ||
y = h_sep if _Ge[idx] > 25 else 0 | ||
# 从背景图中裁剪出对应位置的小块 | ||
img_cut = _img.crop((x, y, x + w_sep, y + h_sep)) | ||
# 将小块拼接到新图中 | ||
new_x = idx % 26 * 10 | ||
new_y = h_sep if idx > 25 else 0 | ||
new_img.paste(img_cut, (new_x, new_y)) | ||
|
||
if im_show: | ||
new_img.show() | ||
if save_path is not None: | ||
save_path = Path(save_path).resolve().__str__() | ||
new_img.save(save_path) | ||
return new_img | ||
|
||
class Slide3: | ||
def __init__(self, ocr: ddddocr.DdddOcr = ddddocr.DdddOcr(show_ad=False)): | ||
self.ocr = ocr | ||
def calculated_distance(self, bg_url: str, slice_url: str) -> int: | ||
bg = requests.get(bg_url) | ||
bg_image = parse_bg_captcha(bg.content, im_show=False) # 假设不显示,仅用于比较 | ||
slice_image = requests.get(slice_url).content | ||
bg1_bytes = io.BytesIO() | ||
bg_image.save(bg1_bytes, format='PNG') # 注意指定正确的格式 | ||
bg1_bytes.seek(0) | ||
|
||
res = self.ocr.slide_match(slice_image, bg1_bytes.read(), simple_target=True) | ||
return res['target'][0] | ||
|
||
|
||
|
||
def main(): | ||
ocr = ddddocr.DdddOcr(show_ad=False) | ||
bg = requests.get('http://static.geetest.com/pictures/gt/cd0bbb6fe/bg/1a937a358.jpg') | ||
bg_image = parse_bg_captcha(bg.content, im_show=False) # 假设不显示,仅用于比较 | ||
slice_image = requests.get('http://static.geetest.com/pictures/gt/cd0bbb6fe/slice/1a937a358.png').content | ||
bg1_bytes = io.BytesIO() | ||
bg_image.save(bg1_bytes, format='PNG') # 注意指定正确的格式 | ||
bg1_bytes.seek(0) | ||
|
||
res = ocr.slide_match(slice_image, bg1_bytes.read()) | ||
|
||
print(res) | ||
|
||
if __name__ == '__main__': | ||
main() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters