feat: M9 日报结构化入库(HTML 改为写入 MySQL news_report/news_event,report_type=intl)

- 新增 report_db/ 包(models/schema/db,复用 news 项目实现,幂等 upsert)
- reporter.py: _build_report_data + generate_report 写库返回 report_id
- pipeline/cli 适配 report_id 返回值;HTML 渲染/上传保留 deprecated
- 新增 tests/test_report_db.py;.env.example 增加 NEWS_DB_* 配置
- 已部署 pi5 并验证:真实生成 report_id=184(12 事件)+ 幂等覆盖
This commit is contained in:
2026-08-04 11:09:17 +08:00
parent e1ec5f836d
commit d4a55bcaaa
14 changed files with 669 additions and 69 deletions
+45 -21
View File
@@ -2,9 +2,38 @@
# Claude Code 开发约束(English Financial News 项目)
版本:v1.0
版本:v1.1
最后更新:2026-06-21
最后更新:2026-07-23
---
# 〇、命令速查(2026-07-23 实测)
开发环境:
* Python 3.11 + uv + `.venv`(详见第三节)
* 安装依赖:`uv sync`;新增依赖:`uv add 包名`;开发依赖:`uv add --dev 包名`
常用命令:
| 命令 | 用途 |
|------|------|
| `uv run pytest` | 跑全部测试(当前 162 passed / 2 failed,见下方已知问题) |
| `uv run ruff check .` | 代码规范检查(当前 13 错误,9 可自动修复) |
| `uv run en-news pipeline` | M2→M6 完整管道 |
| `uv run en-news report` | 仅生成日报 |
| `uv run en-news search "查询"` | Qdrant 语义检索 |
| `uv run en-news mcp-server` | 启动 M8 MCP 服务 |
| `bash scripts/domestic_full.sh` | 全流程(M1→M6→日报),Pi 上由 crontab 06/12/18/22 调度 |
| `bash scripts/domestic_crawl_8g.sh [源ID]` | 仅 M1 抓取(可单源测试) |
| `bash scripts/pipeline.sh` | M2→M6 管道 |
已知问题:
* `tests/test_crawler.py::test_write_and_load_index_jsonl``test_write_index_jsonl_dedup` 失败 — `crawler/storage.py:load_index()` 硬编码 `data/raw/...` 路径,未使用测试临时目录;
* ruff 未清零(多为 import 排序 I001,可 `--fix`);
* 日报/摘要 Prompt 内嵌在 `scheduler/reporter.py`,尚未拆分到 `prompts/`
---
@@ -16,7 +45,7 @@
核心能力包括:
* 英文财经新闻抓取(Crawl4AI,12 个英文源,部署海外);
* 英文财经新闻抓取(Crawl4AI,12 个活跃源,国内 Pi 独立运行);
* 英文正文提取(trafilatura);
* 全文英译中(LLM DeepSeek);
* 投资事件抽取(LLM);
@@ -99,25 +128,20 @@ M0 → M1 → 同步机制 → M2 → M3 → M4 → M5+M6 → M7+日报 → M8
## 2.4 部署拓扑意识
本项目采用双服务器架构(详见 english-news-plan.md 第二节):
本项目当前为单服务器架构(海外服务器已于 2026-07-14 停用,详见 README):
| 服务器 | SSH | 部署路径 | 职责 |
|--------|-----|---------|------|
| 海外 | `ssh ecs-user@8.217.19.253` | `/opt/intlgrab` | M1 抓取 → rsync 推送 |
| 国内 | `ssh pi@192.168.1.160` | `/home/pi/intlnews` | M2→M8 全链路 + 日报 |
| 国内 | `ssh pi@192.168.1.160` | `/home/pi/intlnews` | M1→M8 全链路 + 日报 |
部署优先级:
* 抓取代码优先在海外服务器测试;
* 其余代码在国内服务器测试;
* 海外验证通过后,抓取代码同步到国内做全链路联调。
历史:海外 `ecs-user@8.217.19.253:/opt/intlgrab` 曾负责 M1 抓取 → rsync 推送,已停用;`scripts/overseas_*.sh``scripts/domestic_sync.sh` 为遗留脚本(未清理)。
编码时注意:
* 海外侧只负责抓取,无 LLM/Embedding 依赖
* 国内侧等待 rsync 同步完成后再启动管道
* 哨兵文件(`SYNC_SENTINEL`)是同步完整性的关键信号
* `data/raw/` 目录在两台服务器上路径一致
* M1 抓取在国内 Pi8GB)以 headful Playwright + HTTP 代理(Shadowsocks + Privoxy)运行,需 Xvfb 虚拟显示器(见 README 前置条件)
* 强反爬源(Reuters / Investing.com / FT)走 Google News RSS 或 RSS 摘要,全文抓取成功率取决于代理线路质量
* 抓取配置按运行环境拆分为 `configs/profiles/2g_headless.yaml``configs/profiles/8g_headful.yaml`,通过环境变量 `EN_NEWS_PROFILE` 选择
* `data/raw/{source_id}/{yyyymmdd}/` 存放抓取原始 HTML + Markdown + index.jsonl,为全管道数据源头
---
@@ -348,8 +372,7 @@ test_xxx.py
* crawlerM1 抓取)
* extractorM2 正文提取)
* dedupM3 去重)
* translatorM4a 翻译
* llmM4b 事件抽取)
* llmM4a 翻译 + M4b 事件抽取,单次 LLM 调用合并输出;`translator/` 为空壳目录,翻译实现在 `llm/`
* embeddingM5 向量生成)
* vectorstoreM6 Qdrant 入库/检索)
* schedulerM7 定时调度)
@@ -428,8 +451,8 @@ prompts/
本项目 Prompt 文件:
* `translation_and_extraction.md` — 翻译 + 事件抽取(单次 LLM 调用合并输出)
* `daily_report.md` — 日报生成 Prompt(五段式结构)
* `search_agent.md` — MCP Agent 深度研究 Prompt
注意:`daily_report.md``search_agent.md` 尚未创建;日报/摘要 Prompt 目前内嵌在 `scheduler/reporter.py`(技术债,待拆分到 prompts/)。
---
@@ -469,13 +492,14 @@ docker compose up -d
注意:
* 海外侧 docker-compose 包含 Crawl4AI + rsync daemon
* 国内侧 docker-compose 包含 Qdrant + 调度器 + MCP 服务。
* 预期形态:docker-compose 包含 Qdrant + 调度器 + MCP 服务(尚未落地)。
不得依赖:
手工安装。
当前状态(2026-07-23 核查):仓库中尚无 Dockerfile / docker-compose.yml,此要求尚未落实,属待办事项。
---
# 十二、Git 提交规范