Skip to content

Commit

Permalink
Merge pull request #83 from Amorter/main
Browse files Browse the repository at this point in the history
自动验证功能
  • Loading branch information
mikumifa authored Jun 6, 2024
2 parents 96f569b + 06ff607 commit 3578244
Show file tree
Hide file tree
Showing 8 changed files with 9,369 additions and 1 deletion.
136 changes: 136 additions & 0 deletions geetest/www/api.py
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
4,416 changes: 4,416 additions & 0 deletions geetest/www/click.js

Large diffs are not rendered by default.

68 changes: 68 additions & 0 deletions geetest/www/click3.py
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))
81 changes: 81 additions & 0 deletions geetest/www/main.py
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()
170 changes: 170 additions & 0 deletions geetest/www/rt.js

Large diffs are not rendered by default.

4,416 changes: 4,416 additions & 0 deletions geetest/www/slide.js

Large diffs are not rendered by default.

79 changes: 79 additions & 0 deletions geetest/www/slide3.py
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()
4 changes: 3 additions & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,6 @@ setuptools~=65.5.1
gradio~=4.27.0
qrcode~=7.4.2
loguru~=0.7.2
webdriver-manager~=4.0.1
webdriver-manager~=4.0.1
ddddocr~=1.4.11
Pillow~=10.3.0

0 comments on commit 3578244

Please sign in to comment.