feat: 极验验证默认无限重试,由登录整体超时兜底

- max_proxy_retries 默认值从10改为0(无限重试)
- _solve_geetest 增加 deadline 参数,超时则主动退出
- login() 计算 deadline 并传递给极验验证
- 前端/Schema/Service 默认值同步更新
This commit is contained in:
yml2213
2026-06-23 23:40:40 +08:00
parent 7711111015
commit 4813eb039d
4 changed files with 13 additions and 6 deletions
+10 -3
View File
@@ -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}")
+1 -1
View File
@@ -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
+1 -1
View File
@@ -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,
+1 -1
View File
@@ -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;
});
// 值变化时自动持久化