From 4813eb039db6df9e59786569c2241f92141991ba Mon Sep 17 00:00:00 2001 From: yml2213 Date: Tue, 23 Jun 2026 23:40:40 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=9E=81=E9=AA=8C=E9=AA=8C=E8=AF=81?= =?UTF-8?q?=E9=BB=98=E8=AE=A4=E6=97=A0=E9=99=90=E9=87=8D=E8=AF=95=EF=BC=8C?= =?UTF-8?q?=E7=94=B1=E7=99=BB=E5=BD=95=E6=95=B4=E4=BD=93=E8=B6=85=E6=97=B6?= =?UTF-8?q?=E5=85=9C=E5=BA=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - max_proxy_retries 默认值从10改为0(无限重试) - _solve_geetest 增加 deadline 参数,超时则主动退出 - login() 计算 deadline 并传递给极验验证 - 前端/Schema/Service 默认值同步更新 --- core/douyu/login.py | 13 ++++++++++--- web/backend/schemas.py | 2 +- web/backend/services/login_service.py | 2 +- web/frontend/src/pages/LoginTasksPage.tsx | 2 +- 4 files changed, 13 insertions(+), 6 deletions(-) diff --git a/core/douyu/login.py b/core/douyu/login.py index c6e72a6..e824da0 100644 --- a/core/douyu/login.py +++ b/core/douyu/login.py @@ -72,7 +72,7 @@ class DouyuLogin: proxy_api_url: Optional[str] = None, timeout: tuple[float, float] = REQUEST_TIMEOUT, max_geetest_retries: int = 5, - max_proxy_retries: int = 10, + max_proxy_retries: int = 0, max_login_retries: int = 3, max_total_time: float = 300, whitelist_uid: str = "", @@ -328,6 +328,7 @@ class DouyuLogin: """ logger.info(f"开始登录账号: {self.account.username}") start_time = time.monotonic() + deadline = start_time + self.max_total_time for attempt in range(1, self.max_login_retries + 1): elapsed = time.monotonic() - start_time @@ -347,7 +348,7 @@ class DouyuLogin: # 2️⃣ 极验 fullpage 验证 logger.info("步骤2: 极验 fullpage 验证...") - validate, seccode = self._solve_geetest(gt, challenge) + validate, seccode = self._solve_geetest(gt, challenge, deadline=deadline) # 3️⃣ 第二次登录(带极验) logger.info("步骤3: 第二次登录(带极验验证)...") @@ -454,7 +455,7 @@ class DouyuLogin: return gt, challenge, code_token, self.session.cookies.get_dict() - def _solve_geetest(self, gt: str, challenge: str) -> Tuple[str, str]: + def _solve_geetest(self, gt: str, challenge: str, deadline: float = 0) -> Tuple[str, str]: """ 解决极验 fullpage 验证(带重试机制) @@ -465,6 +466,8 @@ class DouyuLogin: Args: gt: 极验gt参数 challenge: 极验challenge参数(第一次登录返回的) + deadline: 登录整体超时截止时间(monotonic),0=不限 + challenge: 极验challenge参数(第一次登录返回的) Returns: (validate, seccode) @@ -479,6 +482,10 @@ class DouyuLogin: _SOFT_FAIL_THRESHOLD = 2 # 同一代理连续临时失败2次才换 for attempt in range(max_attempts): + # 超时兜底:极验验证不应超过登录整体时间上限 + if deadline and time.monotonic() > deadline: + raise ValueError(f"极验验证超时(登录整体时间耗尽)") + try: if self.max_proxy_retries > 0: logger.info(f"极验验证尝试 {attempt + 1}/{max_attempts}") diff --git a/web/backend/schemas.py b/web/backend/schemas.py index 2fa585a..ffe57c8 100644 --- a/web/backend/schemas.py +++ b/web/backend/schemas.py @@ -125,7 +125,7 @@ class AccountOut(BaseModel): class LoginBatchRequest(BaseModel): account_ids: list[int] max_geetest_retries: int = 5 - max_proxy_retries: int = 10 # 代理切换次数,0=无限切换直到成功 + max_proxy_retries: int = 0 # 代理切换次数,0=无限切换直到成功 max_login_retries: int = 3 # 登录整体重试次数(换代理从头重跑) max_total_time: float = 300 # 单账号登录总时长上限(秒),超时则放弃 concurrency: int = 3 # 并发数,1-10 diff --git a/web/backend/services/login_service.py b/web/backend/services/login_service.py index b73cf8f..f8ceb90 100644 --- a/web/backend/services/login_service.py +++ b/web/backend/services/login_service.py @@ -29,7 +29,7 @@ class LoginBatchRunner: created_by: int, creator_permissions: list[str], max_geetest_retries: int = 5, - max_proxy_retries: int = 10, + max_proxy_retries: int = 0, max_login_retries: int = 3, max_total_time: float = 300, proxy_config: Optional[ProxyConfigModel] = None, diff --git a/web/frontend/src/pages/LoginTasksPage.tsx b/web/frontend/src/pages/LoginTasksPage.tsx index 9616b77..3e7f79d 100644 --- a/web/frontend/src/pages/LoginTasksPage.tsx +++ b/web/frontend/src/pages/LoginTasksPage.tsx @@ -44,7 +44,7 @@ export default function LoginTasksPage() { }); const [maxProxyRetries, setMaxProxyRetries] = useState(() => { const v = localStorage.getItem('login_max_proxy_retries'); - return v ? Math.max(0, Number(v) || 10) : 10; + return v ? Math.max(0, Number(v) || 0) : 0; }); // 值变化时自动持久化