From 3dded794d765e2b3075f07d555b9e24cdf952aaa Mon Sep 17 00:00:00 2001 From: zhulinsen Date: Wed, 14 Jan 2026 20:20:51 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=E5=A4=9A=E4=B8=AA=20I?= =?UTF-8?q?ssues?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - #23 ETF 筹码分布:跳过 ETF/指数的筹码分布调用 - #16 OpenAI SOCKS 代理:改进错误提示,添加 httpx[socks] 依赖 - #15 大盘复盘报告:添加报告文件保存功能 --- analyzer.py | 21 +++++++++++++++++---- data_provider/akshare_fetcher.py | 7 +++++++ main.py | 9 +++++++++ requirements.txt | 1 + 4 files changed, 34 insertions(+), 4 deletions(-) diff --git a/analyzer.py b/analyzer.py index 42b62bde6..82fc6fd2b 100644 --- a/analyzer.py +++ b/analyzer.py @@ -441,9 +441,14 @@ class GeminiAnalyzer: logger.debug("OpenAI 兼容 API 未配置或配置无效") return + # 分离 import 和客户端创建,以便提供更准确的错误信息 try: from openai import OpenAI - + except ImportError: + logger.error("未安装 openai 库,请运行: pip install openai") + return + + try: # base_url 可选,不填则使用 OpenAI 官方默认地址 client_kwargs = {"api_key": config.openai_api_key} if config.openai_base_url and config.openai_base_url.startswith('http'): @@ -453,10 +458,18 @@ class GeminiAnalyzer: self._current_model_name = config.openai_model self._use_openai = True logger.info(f"OpenAI 兼容 API 初始化成功 (base_url: {config.openai_base_url}, model: {config.openai_model})") - except ImportError: - logger.error("未安装 openai 库,请运行: pip install openai") + except ImportError as e: + # 依赖缺失(如 socksio) + if 'socksio' in str(e).lower() or 'socks' in str(e).lower(): + logger.error(f"OpenAI 客户端需要 SOCKS 代理支持,请运行: pip install httpx[socks] 或 pip install socksio") + else: + logger.error(f"OpenAI 依赖缺失: {e}") except Exception as e: - logger.error(f"OpenAI 兼容 API 初始化失败: {e}") + error_msg = str(e).lower() + if 'socks' in error_msg or 'socksio' in error_msg or 'proxy' in error_msg: + logger.error(f"OpenAI 代理配置错误: {e},如使用 SOCKS 代理请运行: pip install httpx[socks]") + else: + logger.error(f"OpenAI 兼容 API 初始化失败: {e}") def _init_model(self) -> None: """ diff --git a/data_provider/akshare_fetcher.py b/data_provider/akshare_fetcher.py index 40e42260c..d3231b7cf 100644 --- a/data_provider/akshare_fetcher.py +++ b/data_provider/akshare_fetcher.py @@ -648,6 +648,8 @@ class AkshareFetcher(BaseFetcher): 数据来源:ak.stock_cyq_em() 包含:获利比例、平均成本、筹码集中度 + 注意:ETF/指数没有筹码分布数据,会直接返回 None + Args: stock_code: 股票代码 @@ -656,6 +658,11 @@ class AkshareFetcher(BaseFetcher): """ import akshare as ak + # ETF/指数没有筹码分布数据 + if _is_etf_code(stock_code): + logger.debug(f"[API跳过] {stock_code} 是 ETF/指数,无筹码分布数据") + return None + try: # 防封禁策略 self._set_random_user_agent() diff --git a/main.py b/main.py index b3c455996..dd5ac7404 100644 --- a/main.py +++ b/main.py @@ -687,6 +687,15 @@ def run_market_review(notifier: NotificationService, analyzer=None, search_servi review_report = market_analyzer.run_daily_review() if review_report: + # 保存报告到文件 + date_str = datetime.now().strftime('%Y%m%d') + report_filename = f"market_review_{date_str}.md" + filepath = notifier.save_report_to_file( + f"# 🎯 大盘复盘\n\n{review_report}", + report_filename + ) + logger.info(f"大盘复盘报告已保存: {filepath}") + # 推送通知 if notifier.is_available(): # 添加标题 diff --git a/requirements.txt b/requirements.txt index c30553b59..a7ea39ffc 100644 --- a/requirements.txt +++ b/requirements.txt @@ -32,6 +32,7 @@ google-search-results>=2.4.0 # SerpAPI(每月 100 次免费) # 网络请求 requests>=2.31.0 # HTTP 请求 fake-useragent>=1.4.0 # 随机 User-Agent 防封禁 +httpx[socks] # HTTP 客户端 + SOCKS 代理支持(OpenAI 可选依赖) # 数据库 # SQLite 是 Python 内置,无需额外安装