Files
intl_news/continuation.md
T
simon c72a5ed13a feat: AI 模型按场景独立配置(llm_scenes)+ 去重多来源合并
- system.yaml 新增 llm_scenes(translation / daily_report,含用途/方法/模型要求说明)
- load_llm_config(scene=...) 场景覆盖;日报摘要 temperature 0.3 硬编码 → 配置
- M3 去重:唯一篇记录 source_ids(跨源重复合并,首个来源为 source_id)
- source_ids 经翻译透传至 events,日报事件 source 多来源拼接展示(≤3 个)
- 已部署 pi5:merge 实证 10 源合并;日报 report_id=224 正常入库
2026-08-12 09:56:55 +08:00

9.3 KiB
Raw Blame History

continuation.md — English Financial News 项目状态

最后更新:2026-08-12


2026-08-12 会话成果

M9.2:AI 模型按场景配置 + 去重多来源

背景: ① 本项目所有 AI 大模型调用点(M4 翻译+事件抽取、M7 日报 AI 摘要、M5 向量化)此前共用同一套 llm/embedding 配置;② M3 去重跨源重复时丢弃重复篇来源信息。

改动:

文件 改动内容
configs/system.yaml 新增 llm_scenes 段(translation / daily_report,含用途/使用方法/模型要求说明,字段回退 llm 默认段);embedding 段注释说明单一场景原因
llm/client.py _load_system_config(scene) 场景合并;load_llm_config(..., scene) 支持按场景覆盖 provider/model/参数;场景统一用 model 键
llm/pipeline.py load_llm_config(scene="translation")
scheduler/reporter.py _call_llm_simple 用 scene="daily_report";temperature 硬编码 0.3 → config.temperature(技术债清除);新增 _article_source_label() 多来源拼接展示
extractor/models.py / llm/models.py ProcessedArticle / EnTranslatedArticle 新增 source_ids 字段
dedup/pipeline.py unique 初始化 source_ids=[source_id];dup 时 _merge_duplicate_source() 跨日期目录合并来源进唯一篇
llm/extractor.py 同步/异步构造 EnTranslatedArticle 透传 source_ids
tests/ test_llm.py 场景配置 4 用例;test_dedup.py::TestMergeSources 3 用例;test_report_db.py 多来源拼接 2 用例

测试结果: 本地全量 184 passed / 2 failed(原有 test_crawler 路径问题);ruff 无新增。

部署验证(pi5 实盘):

  • scene 配置生效:translation=(v4-flash, 0.1)、daily_report=(v4-flash, 0.3, 1500)
  • 去重合并实证:历史唯一篇 049da7e0c87160dc(barrons 主源)被 9 个跨源重复篇合并 → source_ids 10 个来源
  • 日报仍正常入库:report_id=224(2026-08-12, 15 事件);当天 DeepSeek 摘要 3 次返回空 → 规则兜底,日报未中断(失败处理按设计工作)
  • 多来源展示:_article_source_label 实测 "Barron's, CNBC, Reuters";单源回退正常

已知说明:

  • 历史 3368 个 deduped 旧文件无 source_ids 字段(不回填,向前生效);events 文件由下次 crontab 07:00 用新代码自然带出透传
  • 179 篇全重复(增量正常);138 个跨源重复的 merge 目标多为历史日期目录文件(指纹库 ±30 天窗口所致),非当天 uniques

2026-08-04 会话成果

M9:日报结构化入库(HTML → MySQL)

背景: 与 news 项目对齐,日报内容不再产出 HTML / scp 上传 doorcome,改为写入共用 MySQL myquant 库(表 news_report / news_event,report_type="intl")。历史日报(2026-06-16 ~ 2026-08-03,intl 128 份)已由 news 项目解析入库,本次仅做新日报按相同契约入库。

改动:

文件 改动内容
report_db/(新增) 复用 news 项目实现:models.py(EventRow/ReportData)、schema.py(news_report/news_event DDL)、db.py(load_db_config/connect/init_schema/save_report/fetch_report/exists_report,loguru 换 logging)
scheduler/reporter.py 新增 _build_report_data()(intl 结构:事件全部 section="intl",file_name="" 幂等覆盖,stats 含 pipeline/sentiment/importance/event_types/source_dist);generate_report() 返回 `int
scheduler/pipeline.py run_step_report 适配 report_id 返回值
app/cli.py report 命令打印 report_id
pyproject.toml uv add pymysql;report_db/schema.py 加 E501 per-file-ignore
.env.example / README.md 新增 NEWS_DB_* 配置说明(pi5 经内网直连 192.168.1.10:13306,password 与 news 项目相同)
tests/test_report_db.py(新增) 模型默认值 + _build_report_data 组装(板块/rank、字段映射、标题截断、stats 快照、"?" 归一化)

测试结果: uv run pytest → 174 passed / 2 failed(2 个失败为原有 test_crawler.py index.jsonl 路径问题,与本次无关);ruff 改动文件干净(仅剩原有 _SENTENCE_END N806)。

部署: 已 rsync 至 pi5(/home/pi/intlnews),.env 写入 NEWS_DB_*,uv sync 安装 pymysql,真实生成日报并回读 DB 验证(详见下方)。


2026-07-23 会话成果

investing.com 反爬策略调整

问题: RSS 返回 403(Cloudflare),Web headful 间歇性失败(数据中心 IP 被标记)

改动:

文件 改动内容
crawler/crawler.py magic=True + enable_stealth=True Crawl4AI/Playwright 全自动反检测;--disable-webrtc 防止 IP 泄露;delay_before_return_html=3s 等待 Cloudflare 挑战;remove_consent_popups=True 自动关弹窗;wait_until="domcontentloaded" 避免被 Cloudflare 阻塞;增加列表页 URL 过滤(most-popular-news/trending 等)
crawler/rss_crawler.py 新增 _make_rss_client() 读取 system.yaml 代理配置创建 httpx 客户端;Google News RSS 跳过 article_url_pattern 域名过滤
configs/sources.yaml investing.com:rss_url 切换为 Google News RSS 代理(绕过 Cloudflare),增加 anti_bot_mode: stealth;forexlive → investinglive 迁移
scripts/domestic_crawl_8g.sh HTTP_PROXY/HTTPS_PROXY 移至 .env 加载之前,确保 httpx 继承代理

测试结果(investing.com):

策略 结果
Google News RSS(代理) ✅ 25/25 篇,423 words/篇平均
Web headful 首页 ✅ 可加载,提取 ~25 个文章链接(15s)
Web headful 文章页 ❌ 所有文章页仍被 Cloudflare 拦截(403)

forexlive → investinglive 迁移

问题: forexlive.com 域名 301 重定向到 investinglive.com,_is_valid_article_url 域名过滤拒绝所有链接

改动: sources.yaml — 移除 forexlive 源,新增 investinglive 源

字段 旧值 新值
id forexlive investinglive
name ForexLive InvestingLive
homepage forexlive.com/ investinglive.com/
rss_url forexlive.com/feed investinglive.com/feed
article_url_pattern /(news|technical-analysis|Education)/ /(news|central-banks|commodities|stocks|technical-analysis)/
max_articles 20 25

测试结果: ✅ found=25 success=25,100%,全文 3-9KB/篇(RSS 内嵌完整正文)


当前进度

M0 ✅ 项目骨架
M1 ✅ 新闻抓取(13/13 源,Pi headful Playwright + HTTP 代理)
M2 ✅ 正文提取(trafilatura + MD 回退,增量跳过已处理)
M3 ✅ 三层去重(L1 URL / L2 Content / L3 SimHash,SQLite 指纹库)
M4 ✅ 翻译+事件抽取(DeepSeek v4-flash,事件去重 Prompt 约束)
M5 ✅ 向量生成(DashScope text-embedding-v3,1024 维)
M6 ✅ Qdrant 入库(本地文件模式,语义搜索验证)
M7 ✅ 全链路管道 + 日报(事件级去重 + AI 摘要分批合并 + 防截断)
M8 ✅ MCP 服务(FastMCP 5 个 Tool)

各源抓取状态

源 策略 状态 说明
Reuters Google News RSS ⚠️ 摘要,RSS 稳定 DataDome 反爬无法突破
CNBC CNBC RSS ✅ 稳定 原生 RSS 正常
MarketWatch RSS + stealth ✅ 稳定 RSS 优先,stealth 回退
FT FT RSS ⚠️ 摘要,RSS 稳定 付费墙,全文不可用
Yahoo Finance Yahoo RSS ✅ 稳定 RSS 正常
Investing.com Google News RSS + stealth ✅ RSS 25/篇,Web ❌ 2026-07-23 修复:RSS 改用 Google News 代理
Seeking Alpha RSS + stealth ✅ 稳定 RSS 稳定
Barron's Dow Jones RSS + stealth ✅ 稳定 无原生 RSS,Dow Jones 兜底
WSJ Dow Jones RSS + stealth ✅ 稳定 RSS 正常
Economist RSS + stealth ✅ 稳定 RSS 正常
InvestingLive RSS ✅ 25/篇 100% 2026-07-23 新增(forexlive 迁移)
ZeroHedge FeedBurner RSS ✅ 稳定 RSS 含全文
Forexlive RSS 已失效 ❌ 301→investinglive 已替换为 InvestingLive

待办事项

  1. Investing.com 全文抓取 — Google News RSS 仅摘要,Web headful 仍被 Cloudflare 拦截(需要更好代理线路或住宅 IP)
  2. Reuters 全文 — 同上,DataDome 需要更先进的代理
  3. FT 付费墙 — 需要付费订阅或放弃全文
  4. 海外服务器 crontab 停用 — 确认不再参与流水线后清理
  5. Pi crontab 确认 — 当前 logs/full.log 显示调度正常运行(06/12/18/22 四个时间点)

服务器状态

角色 地址 路径 状态
海外 ecs-user@8.217.19.253 /opt/intlgrab ⏸️ 不再参与流水线
国内 pi@192.168.1.160 /home/pi/intlnews ✅ 全链路独立运行

CLI 命令速查

bash scripts/domestic_full.sh             全流程(M1→M6→日报)
bash scripts/domestic_crawl_8g.sh         仅 M1 headful(可跟源 ID)
bash scripts/domestic_crawl_8g.sh investing  单源测试
PYTHONPATH=. .venv/bin/python3 -c "..."   直接调用 orchestrator