From f94b323ad8f2daa28c9edfbccc0fe38c219837c5 Mon Sep 17 00:00:00 2001 From: yml2213 Date: Mon, 22 Jun 2026 15:54:45 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BC=98=E5=8C=96=E4=BB=A3=E7=90=86=E5=92=8C?= =?UTF-8?q?=E9=87=8D=E8=AF=95=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- core/douyu/proxy.py | 37 ++++++++++++++++------- web/frontend/src/pages/LoginTasksPage.tsx | 1 + web/frontend/src/pages/ProxyPage.tsx | 9 ++---- 3 files changed, 29 insertions(+), 18 deletions(-) diff --git a/core/douyu/proxy.py b/core/douyu/proxy.py index 1d31110..16d1f9d 100644 --- a/core/douyu/proxy.py +++ b/core/douyu/proxy.py @@ -111,24 +111,29 @@ def verify_proxy_url(proxy_url: str, timeout: tuple = (4, 6)) -> tuple[bool, str """ 验证代理是否可用。 + 验证优先级: + 1. 斗鱼主站(最相关,能访问斗鱼才是最终目的) + 2. myip(快速 IP 验证) + 3. 百度 IP 查询(备用) + Returns: (是否可用, 消息) """ proxies = {'http': proxy_url, 'https': proxy_url} targets = [ - 'https://qifu-api.baidubce.com/ip/local/geo/v1/district', - 'https://myip.ipip.net', - 'https://4.ipw.cn', + ('https://www.douyu.com', '斗鱼主站'), + ('https://myip.ipip.net', 'IP验证'), + ('https://qifu-api.baidubce.com/ip/local/geo/v1/district', '百度IP查询'), ] - for url in targets: + for url, label in targets: try: response = requests.get( url, proxies=proxies, timeout=timeout, headers={'User-Agent': 'Mozilla/5.0'}, ) response.raise_for_status() - return True, f'代理可用: {url.split("/")[2]}' + return True, f'代理可用 → {label}' except Exception as e: err_msg = str(e) if 'Tunnel connection failed' in err_msg or '503' in err_msg: @@ -137,7 +142,7 @@ def verify_proxy_url(proxy_url: str, timeout: tuple = (4, 6)) -> tuple[bool, str detail = '连接超时' else: detail = type(e).__name__ - logger.debug(f"代理验证 {url} 失败: {detail}") + logger.debug(f"代理验证 {label} 失败: {detail}") continue return False, '代理验证失败(所有目标不可达)' @@ -147,7 +152,7 @@ def resolve_working_proxy( api_url: str, whitelist_uid: str = "", whitelist_ukey: str = "", - max_attempts: int = 5, + max_attempts: int = 3, log_func=None, ) -> tuple[Optional[str], str]: """ @@ -157,7 +162,7 @@ def resolve_working_proxy( api_url: 代理API地址 whitelist_uid: 白名单UID(启用白名单时传入) whitelist_ukey: 白名单UKEY - max_attempts: 最大尝试次数 + max_attempts: 最大尝试次数(默认3次) log_func: 日志回调函数 (level, message) Returns: @@ -170,8 +175,15 @@ def resolve_working_proxy( getattr(logger, level if level in ('info', 'warning', 'error', 'success') else 'info', logger.info)(msg) synced_whitelist = False + last_error = "" for attempt in range(1, max_attempts + 1): + # 重试之间增加退避延迟,避免代理API返回同一个不可用IP + if attempt > 1: + delay = min(attempt, 3) # 1s, 2s, 3s 上限 + log('info', f'等待 {delay}s 后重试...') + time.sleep(delay) + log('info', f'代理预检 {attempt}/{max_attempts}: 正在获取代理') try: response = requests.get(api_url, timeout=10) @@ -186,6 +198,7 @@ def resolve_working_proxy( if ok: log('success', f'代理预检成功: {proxy_url}') return proxy_url, msg + last_error = msg log('warning', f'代理预检 {attempt}/{max_attempts}: {msg}') continue @@ -203,9 +216,11 @@ def resolve_working_proxy( continue return None, f'白名单同步失败: {sync_msg}' - log('warning', f'代理预检 {attempt}/{max_attempts}: 代理API响应无法解析: {text[:80]}') + last_error = f'代理API响应无法解析' + log('warning', f'代理预检 {attempt}/{max_attempts}: {last_error}: {text[:80]}') except Exception as exc: - log('warning', f'代理预检 {attempt}/{max_attempts}: 代理API请求失败: {exc}') + last_error = f'代理API请求失败: {exc}' + log('warning', f'代理预检 {attempt}/{max_attempts}: {last_error}') - return None, f'代理预检失败,已尝试 {max_attempts} 次' + return None, f'代理预检失败({max_attempts}次尝试均失败): {last_error}' diff --git a/web/frontend/src/pages/LoginTasksPage.tsx b/web/frontend/src/pages/LoginTasksPage.tsx index 3c067ea..c837653 100644 --- a/web/frontend/src/pages/LoginTasksPage.tsx +++ b/web/frontend/src/pages/LoginTasksPage.tsx @@ -139,6 +139,7 @@ export default function LoginTasksPage() { ws.onclose = () => { wsRef.current = null; setWsConnected(false); + setBatchId(null); }; ws.onerror = () => { setWsConnected(false); diff --git a/web/frontend/src/pages/ProxyPage.tsx b/web/frontend/src/pages/ProxyPage.tsx index 5805a7d..c7856e6 100644 --- a/web/frontend/src/pages/ProxyPage.tsx +++ b/web/frontend/src/pages/ProxyPage.tsx @@ -56,6 +56,8 @@ export default function ProxyPage() { }; ws.onclose = () => { wsRef.current = null; + setTesting(false); + setTestingWl(false); }; }; @@ -96,13 +98,6 @@ export default function ProxyPage() { } }; - // WebSocket 关闭后恢复按钮 - useEffect(() => { - if (!wsRef.current) { - setTesting(false); - setTestingWl(false); - } - }, [logs.length === 0]); const logColors: Record = { error: '#ff4d4f',