From a62e7c192f95dc4ac6c29b2959008c05211437ec Mon Sep 17 00:00:00 2001 From: yml2213 Date: Thu, 25 Jun 2026 08:19:18 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BC=98=E5=8C=96=E7=99=BD=E5=90=8D=E5=8D=95?= =?UTF-8?q?=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- core/douyu/proxy_fetcher.py | 43 +++++++++++++++++---------- web/backend/services/login_service.py | 6 ++++ 2 files changed, 33 insertions(+), 16 deletions(-) diff --git a/core/douyu/proxy_fetcher.py b/core/douyu/proxy_fetcher.py index 3195147..abd0d0e 100644 --- a/core/douyu/proxy_fetcher.py +++ b/core/douyu/proxy_fetcher.py @@ -3,10 +3,11 @@ 专为短效代理设计:无池、无冷却、无复用。 每次调用 fetch_new_proxy() 从 API 取 1 个新代理,用完即弃。 -线程安全:白名单同步有全局锁 + 标志位避免重复同步。 +白名单策略:批次启动前调用 warmup_whitelist() 主动同步一次本地出口 IP; +之后 fetch_new_proxy 不再主动检测/同步,遇到代理 API 返回"白名单错误" +时由 ProxyResolver 内部被动同步兜底。 """ -import threading from typing import Optional from loguru import logger @@ -34,22 +35,36 @@ class ProxyFetcher: if whitelist_credentials else None ) - # 跨线程共享:是否已同步过白名单,避免多线程重复同步 - self._synced = False - self._sync_lock = threading.Lock() + + def warmup_whitelist(self) -> tuple[bool, str]: + """批次启动前调用一次:把当前本地出口 IP 同步到白名单。 + + Returns: + (是否需要关注的结果, 提示消息) + - 无白名单凭据时返回 (True, "无白名单凭据,跳过") + - 出口 IP 获取失败 / 同步失败时返回 (False, 原因) + - 同步成功时返回 (True, 同步消息) + """ + if not self._whitelist_syncer: + return True, "无白名单凭据,跳过" + local_ip = self._whitelist_syncer.get_local_exit_ip() + if not local_ip: + return False, "获取本地出口 IP 失败" + ok, msg = self._whitelist_syncer.sync_ip(local_ip) + if ok: + return True, f"出口 IP {local_ip} 已同步: {msg}" + return False, f"出口 IP {local_ip} 同步失败: {msg}" def fetch_new_proxy(self, max_attempts: int = 3) -> Optional[str]: - """从代理 API 获取 1 个可用代理,失败返回 None。""" - if self._whitelist_syncer: - with self._sync_lock: - already_synced = self._synced - else: - already_synced = False + """从代理 API 获取 1 个可用代理,失败返回 None。 + 不主动检测/同步本地出口 IP;如果代理 API 返回"白名单错误", + 由 ProxyResolver 内部被动同步兜底。 + """ resolver = ProxyResolver( api_url=self.api_url, whitelist_syncer=self._whitelist_syncer, - sync_local_exit_ip=bool(self._whitelist_syncer) and not already_synced, + sync_local_exit_ip=False, sync_whitelist_once=False, ) result, msg = resolver.fetch_verified( @@ -57,10 +72,6 @@ class ProxyFetcher: return_all=False, ) - if self._whitelist_syncer and result: - with self._sync_lock: - self._synced = True - if isinstance(result, str): logger.info(f"获取新代理: {result}") return result diff --git a/web/backend/services/login_service.py b/web/backend/services/login_service.py index 75a7fdb..c8e5378 100644 --- a/web/backend/services/login_service.py +++ b/web/backend/services/login_service.py @@ -186,6 +186,12 @@ class LoginBatchRunner: concurrency = self.concurrency self._push_log("info", f"批量登录任务 {batch_id} 开始,共 {len(self.account_ids)} 个账号,并发数: {concurrency}") + # 批次开始前同步一次出口 IP 到白名单,后续 fetch_new_proxy 不再主动同步 + if self._shared_proxy_fetcher: + ok, msg = self._shared_proxy_fetcher.warmup_whitelist() + if msg != "无白名单凭据,跳过": + self._push_log("info" if ok else "warning", f"白名单预热: {msg}") + try: # 创建或复用任务记录(顺序执行,线程安全) task_infos: list[dict] = [] # {task_id, acc_info}