# 国际财经 Deep Research 平台 — 使用手册 > 版本:v1.0 > 最后更新:2026-06-21 > 项目路径:国内 `/home/pi/intlnews` / 海外 `/opt/intlgrab` --- ## 目录 1. [项目概述](#1-项目概述) 2. [部署拓扑](#2-部署拓扑) 3. [环境配置](#3-环境配置) 4. [CLI 命令参考](#4-cli-命令参考) 5. [M1 — 新闻抓取](#5-m1--新闻抓取) 6. [M2 — 正文提取](#6-m2--正文提取) 7. [M3 — 三层去重](#7-m3--三层去重) 8. [M4 — 翻译 + 事件抽取](#8-m4--翻译--事件抽取) 9. [M5 — 向量生成](#9-m5--向量生成) 10. [M6 — Qdrant 入库与检索](#10-m6--qdrant-入库与检索) 11. [M7 — 全链路管道 + 日报](#11-m7--全链路管道--日报) 12. [M8 — MCP 服务](#12-m8--mcp-服务) 13. [数据目录结构](#13-数据目录结构) 14. [定时任务](#14-定时任务) 15. [常见问题](#15-常见问题) --- ## 1. 项目概述 本项目构建面向**国际英文财经新闻**的私有化 Deep Research 平台。 核心能力: - 英文财经新闻抓取(Crawl4AI,12 个源) - 正文提取(trafilatura) - 全文英译中(DeepSeek LLM) - 投资事件抽取(美股代码识别 + 情绪判断 + 重要度评分) - 双语向量知识库(Qdrant,1024 维) - 语义检索(中文自然语言) - MCP 服务(Claude Code / Cherry Studio Agent 深度研究) - 每日 AI 摘要日报(HTML) **本项目不是**:交易系统 / 股票预测系统 / 投资顾问系统。 --- ## 2. 部署拓扑 ``` ┌──────────────────────────────────────────────────┐ │ Overseas Server (海外) │ │ M1 Crawl4AI 抓取 → data/raw/ │ │ 每天 4 次打包 → rsync 推送 │ │ SSH: <海外服务器> │ │ 路径: /opt/intlgrab │ └────────────────────┬─────────────────────────────┘ │ rsync ▼ ┌──────────────────────────────────────────────────┐ │ Domestic Server (国内) │ │ M2 正文提取 → M3 去重 → M4 翻译+事件 │ │ → M5 向量生成 → M6 Qdrant 入库 │ │ → M7 调度 + 日报 → M8 MCP 服务 │ │ SSH: <国内服务器> │ │ 路径: /home/pi/intlnews │ └──────────────────────────────────────────────────┘ ``` --- ## 3. 环境配置 ### 3.1 依赖安装 ```bash cd /home/pi/intlnews uv sync ``` ### 3.2 配置文件 | 文件 | 用途 | 示例 | |------|------|------| | `.env` | API Key / URL(不入 Git) | `DEEPSEEK_API_KEY=sk-xxx` | | `configs/system.yaml` | 功能参数(模型、阈值、超时) | `llm.provider: deepseek` | | `configs/sources.yaml` | 新闻源定义 | 12 个英文财经源 | ### 3.3 必需环境变量(`.env`) ```bash # DeepSeek(M4 翻译+事件抽取) DEEPSEEK_API_KEY=sk-your-key DEEPSEEK_BASE_URL=https://api.deepseek.com # Qwen(备选 LLM) QWEN_API_KEY=sk-your-key QWEN_BASE_URL=https://dashscope.aliyuncs.com/compatible-mode/v1 # DashScope(M5 向量生成) DASHSCOPE_API_KEY=sk-your-key # Qdrant(留空使用本地文件模式) QDRANT_URL=http://localhost:6333 QDRANT_API_KEY= ``` ### 3.4 关键配置项(`configs/system.yaml`) ```yaml crawler: max_memory_mb: 1800 # 串行抓取内存上限 dedup: hamming_distance_threshold: 3 # SimHash 汉明距离阈值 simhash_window_days: 30 # 时间窗口 llm: provider: "deepseek" deepseek_model: "deepseek-v4-flash" concurrency: 3 # LLM 并发数 embedding: provider: "dashscope" dashscope_model: "text-embedding-v3" dimension: 1024 qdrant: collection: "en_finance_news" schedule: day_cutoff_hour: 6 # 新闻日切分点(06:00) ``` --- ## 4. CLI 命令参考 所有命令通过 `uv run en-news` 执行: | 命令 | Milestone | 功能 | |------|-----------|------| | `crawl` | M1 | 抓取英文财经新闻 | | `extract` | M2 | 正文提取 | | `dedup` | M3 | 三层去重 | | `translate` | M4 | 翻译 + 事件抽取 | | `embed` | M5 | 向量生成 | | `index` | M6 | Qdrant 入库 | | `search ` | M6 | 语义检索 | | `pipeline` | M7 | 一键全链路 M2→M6 | | `report` | M7 | 日报生成 | | `mcp-server` | M8 | 启动 MCP 服务 | 常用选项: ```bash # 指定源 uv run en-news crawl --source forexlive uv run en-news extract --source forexlive # 指定 top_k uv run en-news search "美联储利率决议" --top-k 5 # 重建 Qdrant collection uv run en-news index --recreate # 全链路跳过日报 uv run en-news pipeline --skip-report ``` --- ## 5. M1 — 新闻抓取 ### 5.1 手动抓取 ```bash # 抓取所有启用的源 uv run en-news crawl # 只抓取指定源 uv run en-news crawl -s forexlive ``` ### 5.2 新闻源列表 | 源 ID | 名称 | 类型 | |-------|------|------| | reuters | Reuters | 综合财经 | | cnbc | CNBC | 市场新闻 | | marketwatch | MarketWatch | 市场数据 | | ft | Financial Times | 财经深度 | | yahoo_finance | Yahoo Finance | 综合 | | investing | Investing.com | 全球市场 | | seekingalpha | Seeking Alpha | 投资分析 | | barrons | Barrons | 市场评论 | | wsj | WSJ | 综合财经 | | economist | The Economist | 经济分析 | | forexlive | ForexLive | 外汇新闻 | | zerohedge | ZeroHedge | 另类财经 | ### 5.3 反爬策略 部分新闻源设有反爬保护(如 DataDome)。系统支持三种策略,按优先级自动选择: | 优先级 | 策略 | 配置字段 | 说明 | 适用源 | |--------|------|---------|------|--------| | 1 | **RSS 抓取** | `rss_url` | 通过 RSS/Atom Feed 获取文章列表,完全绕过反爬 | MarketWatch ✅ | | 2 | **Stealth 模式** | `anti_bot_mode: "stealth"` | 隐藏 webdriver 特征(`--disable-blink-features=AutomationControlled`) | Reuters(海外内存不足待验证) | | 3 | **Headful 模式** | `anti_bot_mode: "headful"` | 非 headless 浏览器,最像真人 | 重度反爬源回退 | 配置示例(`configs/sources.yaml`): ```yaml - id: "marketwatch" rss_url: "https://feeds.marketwatch.com/marketwatch/topstories" # RSS 优先 anti_bot_mode: "headful" # RSS 失败时回退 - id: "reuters" anti_bot_mode: "stealth" # 无 RSS,直接 stealth ``` **已验证**: | 源 | 方式 | 结果 | |----|------|------| | MarketWatch | RSS | ✅ 10/10 | | WSJ | RSS | ✅ 20/20 | | ForexLive | 标准 headless | ✅ 17/17 | | ZeroHedge | 标准 + URL 过滤 | ✅ 15/15 | | Barron's | RSS (Dow Jones) | ✅ 10/10 | | Reuters | stealth | ⚠️ DataDome | | SeekingAlpha | stealth | ⚠️ PerimeterX | ### 5.4 海外定时抓取 ```cron # crontab(<海外服务器>)— 每天 4 次 # 时序: 抓取(60min) → 打包(5min) → 10min后国内拉取 0 6 * * * cd /opt/intlgrab && bash scripts/overseas_crawl.sh 5 7 * * * cd /opt/intlgrab && bash scripts/overseas_pack.sh 0 12 * * * cd /opt/intlgrab && bash scripts/overseas_crawl.sh 5 13 * * * cd /opt/intlgrab && bash scripts/overseas_pack.sh 0 18 * * * cd /opt/intlgrab && bash scripts/overseas_crawl.sh 5 19 * * * cd /opt/intlgrab && bash scripts/overseas_pack.sh 0 22 * * * cd /opt/intlgrab && bash scripts/overseas_crawl.sh 5 23 * * * cd /opt/intlgrab && bash scripts/overseas_pack.sh ``` ### 5.4 增量抓取机制 抓取采用**两层增量**确保不重复下载和存储: | 层级 | 位置 | 机制 | |------|------|------| | 抓取层 | `_extract_article_urls` | 读取当日 `index.jsonl` 中已抓取的 url_hash,跳过已存在的 URL,不重复下载 | | 存储层 | `write_index_jsonl` | 追加写入前再次检查 url_hash,已存在则跳过 | 同一天内多次执行 `crawl`,只有新文章才会被下载和存储。 ### 5.5 产物 ``` data/raw/{source_id}/{YYYYMMDD}/ ├── {url_hash}.html # 原始 HTML ├── {url_hash}.md # Crawl4AI Markdown └── index.jsonl # 文章索引 ``` --- ## 6. M2 — 正文提取 ### 6.1 执行 ```bash # 提取所有源 uv run en-news extract # 提取指定源 uv run en-news extract -s forexlive ``` ### 6.2 技术方案 - 优先使用 Crawl4AI 输出的 Markdown - 回退 `trafilatura` 英文正文提取 - 最小正文字数阈值:50 词 ### 6.3 产物 ``` data/processed/{source_id}/{YYYYMMDD}/ ├── {url_hash}.json # ProcessedArticle └── index.jsonl # 处理索引 ``` --- ## 7. M3 — 三层去重 ### 7.1 执行 ```bash uv run en-news dedup ``` ### 7.2 去重逻辑 | 层级 | 方法 | 说明 | |------|------|------| | L1 | URL Hash | 完全相同 URL 直接命中 | | L2 | 内容 Hash | 标准化后 SHA1[:16] 匹配(去标点/空白) | | L3 | SimHash | 字符 3-gram,汉明距离 ≤ 3,30 天窗口 | ### 7.3 产物 ``` data/deduped/{YYYYMMDD}/ ├── uniques/{url_hash}.json # 唯一文章 └── index.json # 去重索引 data/dedup/fingerprints.sqlite3 # 指纹库 ``` --- ## 8. M4 — 翻译 + 事件抽取 ### 8.1 执行 ```bash uv run en-news translate ``` ### 8.2 技术方案 - **Provider**: DeepSeek v4-flash(默认)/ Qwen 备选 - **单次调用**:翻译 + 事件抽取合并,节省 token - **并发**:3 线程(`system.yaml` → `llm.concurrency`) - **重试**:3 次指数退避(1s → 2s → 4s) ### 8.3 输出格式 ```json { "title": "Fed Holds Rates Steady as Markets Rally", "title_zh": "美联储维持利率不变,市场上涨", "content_en": "The Federal Reserve held...", "content_zh": "美联储周三维持利率不变...", "events": [ { "event_type": "央行决议", "stock_codes": [], "sentiment": "neutral", "importance": 5, "summary_zh": "美联储维持利率不变,市场反弹" } ] } ``` ### 8.4 14 种事件类型 `财报披露` `并购收购` `产品发布` `监管政策` `宏观经济` `央行决议` `行业动态` `技术突破` `高管变动` `诉讼法律` `市场异动` `地缘政治` `大宗商品` `外汇波动` `其他` ### 8.5 产物 ``` data/events/{YYYYMMDD}/ ├── {url_hash}.json # EnTranslatedArticle └── index.json # 事件索引 ``` --- ## 9. M5 — 向量生成 ### 9.1 执行 ```bash uv run en-news embed ``` ### 9.2 技术方案 - **Provider**: DashScope `text-embedding-v3` - **维度**: 1024 - **嵌入文本**: `标题: {title_zh}` + `事件: [{sentiment}] {event_type} 重要度{n} {summary_zh}` + `正文: {content_zh[:3000]}` - **截断**: 4000 字符上限 ### 9.3 产物 ``` data/embeddings/{YYYYMMDD}/ ├── {url_hash}.json # EmbeddingResult(1024 维) └── index.json # 向量索引 ``` --- ## 10. M6 — Qdrant 入库与检索 ### 10.1 入库 ```bash # 增量入库 uv run en-news index # 重建 collection(清空旧数据) uv run en-news index --recreate ``` ### 10.2 语义搜索 ```bash # 基本搜索 uv run en-news search "美联储利率决议" # 指定返回条数 uv run en-news search "伊朗霍尔木兹海峡" --top-k 5 ``` ### 10.3 技术方案 - **模式**: 本地文件(`data/qdrant_storage/`),无需 Docker - **Collection**: `en_finance_news` - **距离**: Cosine - **Payload**: title / title_zh / url / source_id / events / content_zh_preview ### 10.4 产物 ``` data/qdrant_storage/ # Qdrant 本地文件存储 ``` --- ## 11. M7 — 全链路管道 + 日报 ### 11.1 手动全链路运行(完整流程) 当需要手工执行完整的数据处理流程时,按顺序执行以下命令: ```bash # 步骤 1(海外): 抓取英文财经新闻 ssh <海外服务器> "cd /opt/intlgrab && uv run en-news crawl" # 步骤 2(海外): 打包 raw 数据 ssh <海外服务器> "cd /opt/intlgrab && bash scripts/overseas_pack.sh" # 步骤 3(国内): 拉取海外数据 cd /home/pi/intlnews && bash scripts/domestic_sync.sh # 步骤 4: 一键全链路 M2→M6 + 日报 cd /home/pi/intlnews && uv run en-news pipeline ``` 也可以分步执行(适合调试): ```bash # 分步模式 uv run en-news extract # M2: 正文提取 uv run en-news dedup # M3: 三层去重 uv run en-news translate # M4: 翻译 + 事件抽取 uv run en-news embed # M5: 向量生成 uv run en-news index # M6: Qdrant 入库 uv run en-news report # 日报生成 ``` ### 11.2 一键管道(自动) ```bash # 全链路 M2→M6 + 日报 uv run en-news pipeline # 跳过日报生成 uv run en-news pipeline --skip-report # 只生成日报 uv run en-news report ``` ### 11.2 管道步骤 ``` M2 extract → M3 dedup → M4 translate → M5 embed → M6 index → 日报 ``` 每步失败记录日志但不阻断后续步骤(降级继续)。 ### 11.3 HTML 日报 日报包含五个板块: 1. 🤖 **AI 摘要** — LLM 根据当日 important≥4 事件生成要点总结 2. 🔥 **重要事件** — 高重要度事件表格(标题/情绪/重要度/摘要/链接) 3. 📊 **数据总览** — M1→M6 管道统计数据 4. 📈 **情绪分布** — 利好/利空/中性比例条 + 重要度分布 5. 📋 **事件类型 TOP 10** 日报输出:`data/reports/intl_news_daily_{YYYYMMDD}.html`(约 9KB),同时自动上传到 `https://echart.doorcome.cn/research/{YYYYMMDD}/intl_news_daily_{YYYYMMDD}.html` ### 11.4 国内定时调度 ```cron # crontab(<国内服务器>)— 每天 3 次 # 全流程:SSH 触发海外打包 → 下载 → 管道串行 M2→M6 → 日报 0 7 * * * cd /home/pi/intlnews && bash scripts/domestic_full.sh 0 12 * * * cd /home/pi/intlnews && bash scripts/domestic_full.sh 0 18 * * * cd /home/pi/intlnews && bash scripts/domestic_full.sh ``` `domestic_full.sh` 统一完成:远程打包 → 同步 → 管道 → 日报。 --- ## 12. M8 — MCP 服务 ### 12.1 启动 ```bash uv run en-news mcp-server ``` ### 12.2 可用 Tool | Tool | 功能 | 示例 | |------|------|------| | `search_news` | 语义检索新闻 | `search_news("美联储利率决议")` | | `search_by_stock` | 美股代码检索 | `search_by_stock("AAPL")` | | `search_by_sentiment` | 按情绪检索 | `search_by_sentiment("加息", sentiment="negative")` | | `get_today_events` | 当日重要事件 | `get_today_events(importance_min=4)` | | `get_stats` | 系统统计 | `get_stats()` | ### 12.3 Claude Code 配置 在 Claude Code 的 MCP 配置中添加: ```json { "mcpServers": { "intl-news": { "command": "uv", "args": ["run", "en-news", "mcp-server"], "cwd": "/home/pi/intlnews" } } } ``` --- ## 13. 数据目录结构 ``` data/ ├── raw/ # M1: 原始抓取 │ └── {source_id}/{YYYYMMDD}/ │ ├── {url_hash}.html │ ├── {url_hash}.md │ └── index.jsonl ├── processed/ # M2: 正文提取 │ └── {source_id}/{YYYYMMDD}/ │ └── {url_hash}.json ├── dedup/ # M3: 指纹库 │ ├── fingerprints.sqlite3 │ └── {YYYYMMDD}/ │ ├── uniques/{url_hash}.json │ └── index.json ├── events/ # M4: 翻译+事件 │ └── {YYYYMMDD}/ │ └── {url_hash}.json ├── embeddings/ # M5: 向量 │ └── {YYYYMMDD}/ │ └── {url_hash}.json ├── qdrant_storage/ # M6: Qdrant 本地存储 └── reports/ # M7: 日报 └── intl_news_daily_{YYYYMMDD}.html ``` --- ## 14. 定时任务 ### 14.1 时间线 ``` 海外 国内 ───────────────────────────── ───────────────────────── 06:00 crawl (≈60min) 07:00 全流程(打包→下载→管道→日报) 12:00 crawl (≈60min) 12:00 全流程 18:00 crawl (≈60min) 18:00 全流程 22:00 crawl (≈60min) (夜间 crawl 结果次日 07:00 处理) ``` 国内 `domestic_full.sh` 流程:`SSH触发海外打包 → 下载 → M2→M3→M4→M5→M6 → 日报`(串行)。 ### 14.2 新闻日定义 - 切分点:`day_cutoff_hour: 6`(凌晨 06:00) - 当天 06:00 至次日 05:59 属于同一个新闻日 - 例如:2026-06-19 04:00 → 新闻日 "20260618" --- ## 15. 常见问题 ### Q: 如何新增新闻源? 编辑 `configs/sources.yaml`,添加源配置: ```yaml - id: "new_source" name: "New Source Name" enabled: true homepage: "https://example.com/finance/" article_url_pattern: "/news/[^/]+/" js_render: false max_articles_per_run: 30 ``` ### Q: 翻译质量不好怎么办? 1. 调整 `configs/system.yaml` 中 `llm.temperature`(降低更保守) 2. 编辑 `prompts/translation_and_extraction.md` 优化 Prompt 3. 切换 Provider:`llm.provider: "qwen"` ### Q: Qdrant 检索太慢? - 本地文件模式已足够快(17 条 < 0.01s) - 数据量 > 10 万条时建议切换到 Docker 模式 - 设置 `QDRANT_URL=http://your-server:6333` ### Q: 如何查看日志? ```bash tail -f logs/sync.log # 同步日志(国内) tail -f logs/pipeline.log # 管道日志(国内) tail -f logs/crawl.log # 抓取日志(海外) tail -f logs/pack.log # 打包日志(海外) ``` 日志自动清理:每周日凌晨 3 点删除 14 天前的 `.log` 文件(`scripts/cleanup_logs.sh`)。 ### Q: 数据如何备份? ```bash # 备份整个 data 目录 tar czf intlnews_backup_$(date +%Y%m%d).tar.gz data/ ``` --- ## 附录:技术栈 | 组件 | 技术 | |------|------| | 语言 | Python 3.11 | | 包管理 | uv + pyproject.toml | | 抓取 | Crawl4AI + Playwright | | 正文提取 | trafilatura | | 去重 | SimHash + SQLite | | LLM | DeepSeek v4-flash(OpenAI SDK) | | Embedding | DashScope text-embedding-v3 | | 向量库 | Qdrant(本地文件模式) | | MCP | FastMCP | | CLI | Typer | | 配置 | YAML + .env | | 数据模型 | Pydantic v2 |