# project_plan.md # A股 Deep Research 私有投研平台项目计划 版本:v1.0 最后更新:2026-06-16 --- # 一、项目目标 构建一个面向 A 股投资研究的私有化 Deep Research 平台,实现: 1. 自动抓取国内财经新闻网站; 2. 支持 JavaScript 动态渲染网站; 3. 自动提取中文新闻正文; 4. 自动去重; 5. 利用大模型抽取投资事件; 6. 自动生成向量知识; 7. 构建长期财经知识库; 8. 支持语义检索; 9. 支持 Cherry Studio、Claude Code、MCP 调用; 10. 自动生成 A 股投研分析报告。 本项目定位: > 「A 股研究辅助平台」,而非自动交易系统。 --- # 二、总体技术架构 Crawl4AI (网页抓取) ↓ GNE (中文正文提取) ↓ 标准化处理 ↓ 新闻去重 ↓ LLM 投资事件抽取 ↓ Embedding 向量化 ↓ Qdrant 向量知识库 ↓ MCP 服务 ↓ Cherry Studio / Claude Code Agent ↓ A 股深度研究分析 --- # 三、开发原则 Claude Code 在整个开发过程中必须遵守以下原则。 ## 3.1 分阶段开发原则 严禁一次性生成整个项目。 必须按照 Milestone(里程碑)逐步开发。 每个阶段必须: * 独立运行; * 独立测试; * 独立验收。 验收通过后再进入下一阶段。 --- ## 3.2 生产级代码原则 所有生成代码必须满足: * 使用 Python 类型注解; * 必须记录日志; * 必须具备异常处理; * 必须支持重试机制; * 不允许硬编码配置; * 配置必须可修改; * 必要时编写测试代码。 禁止为了简洁而牺牲可维护性。 --- ## 3.3 配置驱动原则 网站抓取规则不得写死。 所有新闻源配置必须来自 YAML 文件。 示例: sources.yaml * id: sina enabled: true homepage: https://finance.sina.com.cn article_selector: article title_selector: h1 --- ## 3.4 中文优先原则 本系统主要服务于中文财经研究。 优先支持: * 财联社 * 东方财富 * 新浪财经 * 证券时报 * 中国证券网 * 界面新闻 * 第一财经 * 雪球 后续支持: * 微博财经 * 微信公众号 * B站财经UP主 * 知乎专栏 --- ## 3.5 可持续演进原则 后续新增网站时: 不得修改已有核心逻辑。 新增网站应仅通过: * 修改配置; * 新增适配器; 完成扩展。 --- # 四、推荐项目结构 a_share_research/ ├─ app/ │ ├─ crawler/ # 抓取模块 ├─ extractor/ # 正文提取 ├─ dedup/ # 去重模块 ├─ llm/ # 大模型抽取 ├─ embedding/ # 向量生成 ├─ vectorstore/ # Qdrant ├─ scheduler/ # 定时任务 ├─ mcp/ # MCP服务 ├─ api/ # 对外接口 ├─ configs/ # 配置文件 ├─ prompts/ # Prompt模板 ├─ tests/ # 测试 ├─ scripts/ # 工具脚本 ├─ logs/ ├─ docs/ │ ├─ main.py ├─ pyproject.toml ├─ docker-compose.yml ├─ README.md ├─ CLAUDE.md ├─ continuation.md └─ project_plan.md --- # 五、Milestone 1:新闻抓取模块 目标: 建立稳定可靠的新闻抓取能力。 任务: 1. 安装 Crawl4AI; 2. 验证浏览器环境; 3. 实现 crawler 模块; 4. 从 YAML 读取网站配置; 5. 支持异步并发抓取; 6. 支持导出原始 HTML; 7. 支持导出 Markdown; 8. 本地保存抓取结果。 交付物: crawler/ configs/sources.yaml tests/test_crawler.py 验收标准: * 至少支持 5 个财经网站; * 抓取成功率 ≥ 90%; * 抓取失败自动重试。 --- # 六、Milestone 2:正文提取模块 目标: 提取高质量中文新闻正文。 任务: 1. 集成 GNE; 2. 实现 extractor 模块; 3. 自动去除广告; 4. 自动去除相关推荐; 5. 自动去除评论区; 6. 提取: * 标题 * 正文 * 发布时间 * 作者 * 来源 统一输出格式: { "title":"", "content":"", "publish_time":"", "author":"", "source":"" } 交付物: extractor/ tests/test_extractor.py 验收标准: 主流财经网站正文提取效果达到人工可接受水平。 --- # 七、Milestone 3:新闻去重 目标: 避免重复新闻污染知识库。 任务: 实现三层去重: 第一层: URL Hash 去重; 第二层: 正文 Hash 去重; 第三层: 模糊匹配去重。 交付物: dedup/ tests/test_dedup.py 验收标准: 重复新闻比例 ≤ 5%。 --- # 八、Milestone 4:投资事件抽取 目标: 将新闻转换为结构化投资信息。 任务: 调用 DeepSeek 或 Qwen API。 抽取: * 股票代码; * 公司名称; * 所属行业; * 利好/利空; * 影响程度; * 事件类型。 输出 JSON。 示例: { "stock_codes":["300750"], "company_names":["宁德时代"], "industries":["锂电池"], "sentiment":"positive", "importance":5, "event_type":"合作签约" } 交付物: llm/ prompts/ 验收标准: JSON 输出成功率 ≥ 95%。 --- # 九、Milestone 5:Embedding 向量化 目标: 构建语义检索能力。 任务: 支持: 本地模型: * BGE-M3; 远程API: * Qwen Embedding; * 百炼 Embedding。 输出: List[float] 交付物: embedding/ 验收标准: 向量生成稳定可用。 --- # 十、Milestone 6:Qdrant 向量知识库 目标: 建立长期财经知识库。 任务: 1. Docker 部署 Qdrant; 2. 创建 Collection; 3. 定义 Payload; 4. 写入向量; 5. 支持检索; 6. 支持过滤。 交付物: docker-compose.yml vectorstore/ 验收标准: Top-K 检索正确。 --- # 十一、Qdrant Payload 规范 { "id":"", "title":"", "content":"", "publish_time":"", "source":"", "url":"", ``` "stock_codes":[], "company_names":[], "industries":[], "sentiment":"", "importance":0, "event_type":"" ``` } --- # 十二、Milestone 7:定时任务 目标: 实现无人值守更新。 任务: 集成 APScheduler。 执行时间: 07:00 12:00 18:00 22:00 执行流程: 抓取 ↓ 正文提取 ↓ 新闻去重 ↓ LLM 抽取 ↓ Embedding ↓ Qdrant 入库 交付物: scheduler/ 验收标准: 能够长期稳定运行。 --- # 十三、Milestone 8:MCP 服务 目标: 支持 Agent 调用知识库。 任务: 实现 MCP 工具: search_news search_company_news search_industry_news search_stock_events search_sentiment_trend 验收标准: Cherry Studio 能够成功调用。 交付物: mcp/ --- # 十四、Milestone 9:投研 Agent 目标: 生成 A 股深度研究报告。 任务: 设计 Prompt。 支持: * 公司分析; * 行业分析; * 利好利空梳理; * 新闻时间线追踪; * 情绪变化分析; * 风险识别; * 投资逻辑总结。 输出: 结构化研究报告。 交付物: docs/agent_prompt.md 验收标准: 研究报告具备实际参考价值。 --- # 十五、运行与运维要求 所有服务必须支持 Docker 部署。 要求: * 使用 .env 管理敏感配置; * API Key 禁止提交至 Git; * 日志自动轮转; * 支持增量更新; * 支持断点恢复; * 提供健康检查接口。 --- # 十六、非目标(Non-Goals) 本项目不负责: * 自动下单交易; * 股票价格预测; * 提供投资建议; * 保证投资收益; * 替代人工决策。 本项目定位为: > A 股研究辅助与知识管理平台。 --- # 十七、Claude Code 执行规则 Claude Code 必须严格遵守: 1. 每次只完成一个 Milestone; 2. 完成后停止并等待人工验收; 3. 每个阶段更新 README; 4. 未经允许不得重构已验收模块; 5. 必须保持向后兼容; 6. 需求冲突时主动提问; 7. 优先保证稳定性和可维护性; 8. 不得追求炫技式实现; 9. 所有关键设计必须记录到 docs/; 10. 每次提交前必须确认代码可运行。 项目完成标准: > 用户能够通过 Cherry Studio 提出类似: “请分析宁德时代最近30天的利好利空变化,并给出主要投资逻辑演化过程。” 系统自动检索知识库、分析新闻事件,并生成完整研究报告。 --- # 十八、Milestone 10:日报结构化入库(前后端分离数据层) > 状态:✅ 已实施(2026-08-03,等待人工验收) > 范围:本项目只负责「日报内容生成 + 结构化存入 MySQL」,**不实现 API 与前端**(由用户另行实现)。 ## 背景与决策 | 决策点 | 结论 | | --- | --- | | DB | 192.168.1.10:13306(pi 上 autossh 隧道 → doorcome.cn:3306 MariaDB 10.11.18),业务库 `myquant`,表前缀 `news_` | | API / 前端 | 用户另行实现,本项目只保证数据完整、表结构文档清晰 | | 日报生成 | 完全切换:只存 DB + 前端渲染,不再生成 HTML 静态文件 | | 历史数据 | doorcome `/var/www/html/echart/research/{YYYYMMDD}/` 下 178 份 `*_news_daily_*.html`(finance×50 + intl×128,日期 20260608~20260803),解析入库 | ## 表结构设计 ### news_report(日报主表) ```sql CREATE TABLE IF NOT EXISTS news_report ( id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY, report_date DATE NOT NULL COMMENT '日报日期', report_type VARCHAR(16) NOT NULL COMMENT 'finance=A股日报 / intl=国际财经日报', file_name VARCHAR(160) NOT NULL DEFAULT '' COMMENT '源文件名(历史解析);新生成可为空', generated_at DATETIME NOT NULL COMMENT '生成时间', ai_summary TEXT NULL COMMENT 'AI 摘要全文', stats JSON NULL COMMENT '数据总览统计快照(管道/情绪/重要度/事件类型/来源分布)', created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, UNIQUE KEY uk_report_file (report_date, report_type, file_name), KEY idx_report_date (report_date) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='每日日报主表'; ``` ### news_event(日报事件明细,新闻联播/财经新闻/公告调研/intl 事件统一入此表) ```sql CREATE TABLE IF NOT EXISTS news_event ( id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY, report_id BIGINT UNSIGNED NOT NULL COMMENT 'FK → news_report.id', section VARCHAR(16) NOT NULL COMMENT '板块: xwlb=新闻联播 / news=财经新闻 / cninfo=公告调研 / intl=国际重要事件', rank INT NOT NULL DEFAULT 0 COMMENT '板块内序号', importance INT NULL COMMENT '重要度 1-5', event_type VARCHAR(64) NULL COMMENT '事件类型', title VARCHAR(512) NOT NULL COMMENT '标题', summary TEXT NULL COMMENT '摘要/正文', sentiment VARCHAR(8) NULL COMMENT 'positive/negative/neutral', source VARCHAR(64) NULL COMMENT '来源', url VARCHAR(512) NULL COMMENT '原文链接', created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, KEY idx_report_section (report_id, section) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='日报事件明细'; ``` 设计说明: - 数据总览统计(M1→M6 管道、各源数据、情绪/重要度/事件类型/来源分布)以 JSON 快照存 `news_report.stats`,前端自行解析。 - 幂等:导入/生成按 `(report_date, report_type, file_name)` 唯一键,重复执行跳过或覆盖,不产生重复行。 - 历史同一天多次生成(intl 一日 3 次)保留多行,前端取最新。 ## 阶段划分(每阶段验收后进入下一阶段) ### M10-A:DB 连接层与建表 - `uv add pymysql`(纯 Python 驱动,无编译依赖) - 新包 `report_db/`:`db.py`(连接、事务、建表)、`schema.py`(DDL) - `.env` 新增 `NEWS_DB_HOST / NEWS_DB_PORT / NEWS_DB_USER / NEWS_DB_PASSWORD / NEWS_DB_NAME`(默认 myquant),`.env.example` 同步 - 验收:连接成功、`news_report` / `news_event` 建表成功;`tests/test_report_db.py` 通过(测试用 sqlite3 内存模拟同构 SQL,真实 MySQL 走 integration 标记) ### M10-B:历史日报解析入库 - 一次性将 doorcome 178 份 HTML 拉到 `data/reports_history/` - 新包 `report_import/`:`parser.py`(finance/intl 两类 HTML → 结构化 dict,容错缺板块)、`importer.py`(幂等入库) - CLI 子命令:`a-share report-import [--date YYYYMMDD] [--type finance|intl]`(默认全量) - 验收:178 份全部入库,`SELECT COUNT(*)` 与文件数一致;抽查 finance/intl 各 2 份字段正确;重复执行不产生重复行 ### M10-C:日报生成改造(完全切换) - `scheduler/reporter.py`:`generate_report()` 改为「收集结构化数据 → 写入 news_report/news_event」,移除 `_render_html` / `_upload` 调用(函数可保留但不再触发) - `scheduler/pipeline.py` 调用签名保持兼容(仍调 `generate_report(day_str)`) - 验收:`uv run a-share report --date YYYYMMDD` 后 DB 出现当日记录且无 HTML 文件产出;AI 摘要、事件行、stats JSON 完整 ### M10-D:文档与收尾 - `docs/db_schema.md`:完整表结构 + 字段说明 + 示例数据(供用户实现 API/前端) - 更新 README、continuation.md;提交信息 `feat: 日报结构化入库` ## 待确认项(不阻塞开发,部署前需用户决策) 1. **生产连接**:pi5(192.168.1.160)无法直连 `192.168.1.10:13306`(隧道只绑 loopback)。可选:a) pi 的 autossh 改为绑定 0.0.0.0(需改 pi 系统配置)b) pi5 自建隧道 c) 其他 2. **intl 日报生成方**:项目代码中无 intl 生成逻辑(doorcome 上另有来源)。历史解析照做;未来 intl 新日报如需入库,由生成方按同一表结构写入 3. **个股日报**(002714.SZ_0724.html 等 research 根目录文件):本期不处理,如需请另行提出 —— project_plan.md 结束 ——