# 日报结构化入库:数据库表结构与数据契约 > 版本:v1.0 | 2026-08-03 > 用途:供 API / 前端对接读取日报数据。表位于 MySQL `myquant` 库,表前缀 `news_`。 > 连接:`192.168.1.10:13306`(pi 上 autossh 隧道 → doorcome.cn:3306 MariaDB 10.11),用户 `myquant`(密码在服务器 `.env` 的 `NEWS_DB_PASSWORD`)。 --- ## 1. 表结构 ### 1.1 news_report(日报主表,一行 = 一份日报) | 字段 | 类型 | 说明 | | --- | --- | --- | | id | BIGINT UNSIGNED PK | 自增主键 | | report_date | DATE | 日报日期 | | report_type | VARCHAR(16) | `finance`=A 股日报 / `intl`=国际财经日报 | | file_name | VARCHAR(160) | 历史文件源文件名;**新生成日报为空字符串 `""`** | | generated_at | DATETIME | 生成时间 | | ai_summary | TEXT | AI 摘要全文(含换行,按条目分行) | | stats | JSON | 数据总览统计快照(见第 3 节),可为 NULL | | created_at | DATETIME | 入库时间 | 唯一键:`(report_date, report_type, file_name)` —— 历史同一天多次生成(intl 一日 3 次)保留多行;新生成日报 `file_name=''` 每天每类型仅一行,重复生成覆盖。 ### 1.2 news_event(日报事件明细,一行 = 一条事件) | 字段 | 类型 | 说明 | | --- | --- | --- | | id | BIGINT UNSIGNED PK | 自增主键 | | report_id | BIGINT UNSIGNED | FK → news_report.id | | section | VARCHAR(16) | 板块:`xwlb`=新闻联播 / `news`=财经新闻 / `cninfo`=公告调研 / `intl`=国际重要事件 | | rank | INT | 板块内序号(1 起) | | importance | INT NULL | 重要度 1-5 | | event_type | VARCHAR(64) NULL | 事件类型(如 宏观经济/地缘政治/新闻联播/公告) | | title | VARCHAR(512) | 标题 | | summary | TEXT NULL | 摘要/正文 | | sentiment | VARCHAR(8) NULL | `positive` / `negative` / `neutral` | | source | VARCHAR(64) NULL | 来源(如 `cls`、`investinglive.com`) | | url | VARCHAR(512) NULL | 原文链接(新闻联播为空) | | created_at | DATETIME | 入库时间 | 索引:`idx_report_section (report_id, section)`。 --- ## 2. 数据契约 - **幂等语义**:同一 `(report_date, report_type, file_name)` 重复写入会覆盖主表并全量替换事件(DELETE + INSERT),不会产生重复行。 - **取最新**:同一天存在多份时(历史 intl 一日 3 次),前端按 `generated_at` 取最新;新日报 `file_name=''` 每天唯一。 - **板块差异**:finance 日报含 `xwlb`+`news`+`cninfo` 三板块;intl 日报仅 `intl` 板块。前端按 `section` 过滤展示。 - **历史覆盖范围**:2026-06-16 ~ 2026-08-03,共 177 行(finance 49 + intl 128;finance 少 1 因为两个目录存在同名文件被幂等合并)。事件总计 4222 条。 --- ## 3. stats JSON 结构 `news_report.stats` 为数据总览快照,前端自行解析。finance 与 intl 的 key 集合不同: | key | finance | intl | 内容 | | --- | --- | --- | --- | | `pipeline` | ✅ | ✅ | M1→M6 管道各环节数量:`{label: 数量}` | | `sources` | ✅ | — | 各新闻源文章数:`{源名: 数量}` | | `news` | ✅ | — | 新闻统计:`{total, hi_threshold, sentiments, importances, event_types}` | | `cninfo` | ✅ | — | 公告调研统计:`{total, hi_threshold, by_day, announcement, research, irm}` | | `xwlb` | ✅ | — | 联播统计:`{total, date}`(有数据时才有) | | `sentiment` | ✅ | ✅ | 情绪分布(历史文件为图例文本列表;新生成在 `news.sentiments`) | | `importance` | ✅ | ✅ | 重要度分布:`[{重要度, 数量}, ...]` | | `event_types` | ✅ | ✅ | 事件类型 TOP:`[{事件类型, 数量}, ...]` | | `source_dist` | — | ✅ | 文章来源分布:`[{来源, 文章数}, ...]` | > 历史文件与新生成日报的 stats 结构存在差异(历史为 HTML 解析快照,新生成为结构化组装),前端建议按 key 防御性读取。 --- ## 4. 常用查询示例(API 实现参考) ```sql -- 某类型日报列表(取每天最新一份) SELECT r.* FROM news_report r JOIN ( SELECT report_date, report_type, MAX(generated_at) AS g FROM news_report GROUP BY report_date, report_type ) t ON r.report_date = t.report_date AND r.report_type = t.report_type AND r.generated_at = t.g WHERE r.report_type = 'finance' AND r.report_date >= '2026-07-01' ORDER BY r.report_date DESC; -- 某日报的全部事件(按板块) SELECT section, rank, importance, event_type, title, summary, sentiment, source, url FROM news_event WHERE report_id = ? ORDER BY section, rank; -- 最近 N 天重要事件聚合(跨日报检索) SELECT e.* FROM news_event e JOIN news_report r ON r.id = e.report_id WHERE r.report_date >= DATE_SUB(CURDATE(), INTERVAL 7 DAY) AND e.importance >= 4 ORDER BY e.importance DESC, r.report_date DESC; ``` --- ## 5. 相关命令(数据生产侧) ```bash uv run a-share report --date YYYYMMDD # 生成当日日报并入库(finance) uv run a-share report-import # 历史 HTML 全量解析入库(幂等) uv run a-share report-import --date YYYYMMDD --type intl ``` 代码:`report_db/`(连接/写入)、`report_import/`(历史解析/导入)、`scheduler/reporter.py`(日报生成)。