Files
live-hub-py/core/douyu/proxy_fetcher.py
T

85 lines
2.5 KiB
Python

"""简化版代理获取器。
专为短效代理设计:无池、无冷却、无复用。
每次调用 fetch_new_proxy() 从 API 取 1 个新代理,用完即弃。
线程安全:白名单同步有全局锁 + 标志位避免重复同步。
"""
import threading
from typing import Optional
from loguru import logger
from .proxy_resolver import ProxyResolver
from .proxy_whitelist import DouyuWhitelistSyncer
class ProxyFetcher:
"""每次从代理 API 取 1 个新代理,无缓存无复用。"""
def __init__(
self,
api_url: str,
whitelist_platform: str = "xiequ",
whitelist_credentials: dict = None,
):
self.api_url = api_url
self._whitelist_syncer = (
DouyuWhitelistSyncer(
platform=whitelist_platform or "xiequ",
credentials=whitelist_credentials,
)
if whitelist_credentials
else None
)
# 跨线程共享:是否已同步过白名单,避免多线程重复同步
self._synced = False
self._sync_lock = threading.Lock()
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
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_whitelist_once=False,
)
result, msg = resolver.fetch_verified(
max_attempts=max_attempts,
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
if isinstance(result, list) and result:
logger.info(f"获取新代理: {result[0]}")
return result[0]
logger.warning(f"获取代理失败: {msg}")
return None
def get_proxy_fetcher(
api_url: str,
whitelist_platform: str = "xiequ",
whitelist_credentials: dict = None,
) -> ProxyFetcher:
"""获取代理获取器实例。"""
return ProxyFetcher(
api_url,
whitelist_platform=whitelist_platform,
whitelist_credentials=whitelist_credentials,
)