feat: 日报结构化入库(M10 前后端分离数据层)
- 新增 report_db 包: MySQL 连接/建表/幂等写入 (news_report/news_event, myquant 库) - 新增 report_import 包: 历史 178 份日报 HTML 解析入库, 表头驱动列映射 - reporter.py 完全切换: generate_report 结构化入库, 不再生成/上传 HTML - CLI: 新增 report-import 子命令 - 依赖: uv add pymysql; 配置: NEWS_DB_* / REPORT_HISTORY_DIR - 文档: docs/report_db_design.md(实现逻辑), docs/db_schema.md(表结构供 API/前端) - 测试: 24 个单测通过 (parser/builder/models/importer)
This commit is contained in:
@@ -602,5 +602,99 @@ Claude Code 必须严格遵守:
|
||||
|
||||
系统自动检索知识库、分析新闻事件,并生成完整研究报告。
|
||||
|
||||
---
|
||||
|
||||
# 十八、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 结束 ——
|
||||
|
||||
|
||||
Reference in New Issue
Block a user