mirror of
https://github.com/KenanZhu/AutoLibrary.git
synced 2026-06-17 23:13:03 +08:00
a6bc103c73
- 将 _dialogs.py 拆分为 pages/components/ 下的独立文件,Overlay 基类同步移入 - CaptchaHandler / RecordChecker 构造函数不再持有 PageObject,改为方法参数注入 - LoginPage.login() 直接接收 auto_captcha 参数,简化 captcha_solver 调用链 - SeatMapOverlay.selectSeat 引入两层查找:先按 ID 直查,失败后遍历匹配 - 移除 ReserveView 中与 Dialog/Overlay 重复的方法(selectSeat、getAvailableTimeOptions) - AutoLibPages 拆分 __initPagesServices / __initPagesFlows - 修复 RecordsView.MORE_BTN 选择器被错误 snake_case 化(more_btn → moreBtn) Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
102 lines
3.5 KiB
Python
102 lines
3.5 KiB
Python
# -*- coding: utf-8 -*-
|
|
"""
|
|
Copyright (c) 2026 KenanZhu.
|
|
All rights reserved.
|
|
|
|
This software is provided "as is", without any warranty of any kind.
|
|
You may use, modify, and distribute this file under the terms of the MIT License.
|
|
See the LICENSE file for details.
|
|
"""
|
|
import base64
|
|
import queue
|
|
|
|
import ddddocr
|
|
from selenium.common.exceptions import (
|
|
NoSuchElementException,
|
|
TimeoutException,
|
|
)
|
|
|
|
from base.MsgBase import MsgBase
|
|
from pages.LoginPage import LoginPage
|
|
|
|
|
|
class CaptchaHandler(MsgBase):
|
|
|
|
def __init__(
|
|
self,
|
|
input_queue: queue.Queue,
|
|
output_queue: queue.Queue,
|
|
) -> None:
|
|
|
|
super().__init__(input_queue, output_queue)
|
|
self._ocr = ddddocr.DdddOcr()
|
|
|
|
def _autoRecognize(
|
|
self,
|
|
login_page: LoginPage,
|
|
) -> str:
|
|
|
|
try:
|
|
img_src = login_page.getCaptchaImageSrc()
|
|
base64_str = img_src.split(',', 1)[1]
|
|
captcha_img = base64.b64decode(base64_str)
|
|
captcha_text = self._ocr.classification(captcha_img)
|
|
captcha_text = ''.join(filter(str.isalnum, captcha_text)).lower()
|
|
self._showTrace(f"识别到验证码为 : '{captcha_text}'", 20, no_log=True)
|
|
if len(captcha_text) != 4:
|
|
self._showLog("识别到的验证码长度不等于 4 个字符 !", self.TraceLevel.WARNING)
|
|
raise Exception("识别到的验证码长度不等于 4 个字符 !")
|
|
return captcha_text
|
|
except (NoSuchElementException, TimeoutException) as e:
|
|
self._showTrace(f"验证码识别失败 ! : {e}", self.TraceLevel.ERROR)
|
|
return ""
|
|
except (ValueError, OSError) as e:
|
|
self._showTrace(f"验证码识别失败 ! : {e}", self.TraceLevel.ERROR)
|
|
return ""
|
|
except Exception as e:
|
|
self._showTrace(f"验证码识别失败 ! : {e}", self.TraceLevel.ERROR)
|
|
return ""
|
|
|
|
def _manualRecognize(
|
|
self,
|
|
) -> str:
|
|
|
|
try:
|
|
self._showMsg("请输入验证码:")
|
|
captcha_text = self._waitMsg(timeout=15)
|
|
self._showTrace(f"输入的验证码为 : '{captcha_text}'", 20, no_log=True)
|
|
if len(captcha_text) != 4:
|
|
self._showLog("输入的验证码长度不等于 4 个字符 !", self.TraceLevel.WARNING)
|
|
raise Exception("输入的验证码长度不等于 4 个字符 !")
|
|
return captcha_text
|
|
except ValueError as e:
|
|
self._showTrace(f"输入验证码失败 ! : {e}", self.TraceLevel.ERROR)
|
|
return ""
|
|
except Exception as e:
|
|
self._showTrace(f"输入验证码失败 ! : {e}", self.TraceLevel.ERROR)
|
|
return ""
|
|
|
|
def solveCaptcha(
|
|
self,
|
|
login_page: LoginPage,
|
|
auto_captcha: bool = True,
|
|
) -> str:
|
|
|
|
max_attempts = 3
|
|
for _ in range(max_attempts):
|
|
if auto_captcha:
|
|
captcha_text = self._autoRecognize(login_page)
|
|
else:
|
|
self._showTrace("用户未配置自动识别验证码, 请手动输入验证码 !", 20, no_log=True)
|
|
captcha_text = self._manualRecognize()
|
|
if captcha_text:
|
|
return captcha_text
|
|
else:
|
|
if not login_page.refreshCaptcha():
|
|
return ""
|
|
self._showTrace(
|
|
f"验证码识别失败 {max_attempts} 次, 达到最大尝试次数 !",
|
|
self.TraceLevel.WARNING,
|
|
)
|
|
return ""
|