1. 项目概述
A 股 Deep Research 是私有化投研平台,自动完成财经新闻抓取 → 正文提取 → 事件抽取 → 向量化 → 语义检索,通过 MCP 协议接入 Cherry Studio / Claude Code,实现「自然语言提问 → 结构化研究报告」。
技术栈: Python 3.11 · Crawl4AI · GNE · DeepSeek/Qwen · DashScope · Qdrant · APScheduler · MCP
部署: 树莓派 5 (ARM64) /home/pi/news/
2. 快速开始
2.1 安装
cd /home/pi/news
uv sync
cp .env.example .env
# 编辑 .env, 填入 DEEPSEEK_API_KEY 和 DASHSCOPE_API_KEY
uv run python -m playwright install chromium # 仅 M1 抓取需要
2.2 验证
uv run pytest -m "not integration" # 应显示 186 passed
3. 统一 CLI 速查
所有操作通过 a-share 命令完成。
| 命令 | 功能 | 常用参数 |
|---|---|---|
a-share crawl | M1 抓取新闻 | --source cls |
a-share extract | M2 正文提取 | --date 20260616 |
a-share dedup | M3 三层去重 | --date 20260616 --reset |
a-share events | M4 LLM 事件抽取 | --provider qwen --limit 5 |
a-share embed | M5 向量化 | --model text-embedding-v3 |
a-share ingest | M6 Qdrant 入库 | --date 20260616 --recreate |
a-share pipeline | 全链路 (M1→M6) | --once --report |
a-share discover | 分析站点, 生成配置 | --name 中文名 --add --extra URL |
a-share add-entry | 追加入口到已有源 | source_id url1 url2 ... |
a-share report | 生成/上传日报 | --date 20260616 --no-upload |
a-share search | 终端检索知识库 | --source --stock --sentiment --top |
a-share status | 数据总览 | 无参数 |
4. 全链路一键运行
uv run a-share pipeline --once # 一次跑通 M1→M6
uv run a-share pipeline --once --report # 末尾自动生成日报并上传
耗时约 4-5 分钟 (100 篇): crawler ~3min / extractor ~24s / dedup ~2s / llm ~45s / embedding ~10s / qdrant ~4s
只执行部分步骤: uv run a-share pipeline --once --steps crawler,llm
产物路径: data/raw/ (M1) → data/processed/ (M2) → data/deduped/ (M3) → data/events/ (M4) → data/embeddings/ (M5) → data/qdrant_storage/ (M6)
5. 新闻源管理
5.1 查看已有源
配置文件: configs/sources.yaml。内置财联社 / 东方财富 / 新浪财经 / 证券时报 / 第一财经。
5.2 新增站点 (一条命令)
# 自动分析 + 写入 sources.yaml
uv run a-share discover https://example.com/news/ --name 中文名 --add
# 仅预览
uv run a-share discover https://example.com/news/
自动完成: JS 抓取 → 链接提取 → 导航过滤 → 模式聚类 → 正则生成 → yaml 输出。写入时自动空行分隔、序号递增、# ---- N. 名称 ---- 注释头。
5.3 同站多频道
# 一次性分析多入口
uv run a-share discover https://example.com/news/global \
--extra https://example.com/news/china \
--extra https://example.com/news/tech \
--name 中文名 --add
生成的 yaml 自动包含 extra_homepages 字段,抓取时依次访问所有入口,自动去重。
5.4 为已有源追加入口
uv run a-share add-entry wallstreetcn https://xxx.com/news/新频道
自动去重 — 已存在的 URL 跳过。
5.5 验证
uv run a-share crawl --source wallstreetcn
6. cninfo 公告抓取
cninfo(巨潮资讯网)是独立的 A 股公告抓取管道,与新闻抓取分开调度(每天 08:00)。
uv run a-share pipeline --cninfo-once # watchlist 全链路 (公告+调研+IRM)
uv run a-share cninfo --watchlist # 仅公告(关注公司)
uv run a-share cninfo --research # 仅调研
uv run a-share cninfo --irm # 仅互动问答
uv run a-share stock-report # 个股日报
全链路 9 步: 公告→调研→IRM→提取→PDF→去重→LLM→向量→Qdrant。
公告关注列表
uv run a-share watchlist add 300750 宁德时代 --note "动力电池龙头"
uv run a-share watchlist list
uv run a-share watchlist remove 000001
uv run a-share cninfo --watchlist # 只抓关注公司
关注公司公告在日报中置顶并 ⭐ 高亮。配置: configs/watchlist.yaml。
配置: CNINFO_ENABLED CNINFO_DAYS_BACK CNINFO_MAX_PAGES CNINFO_API_BASE CNINFO_PDF_BASE
# 注释。python-dotenv 会把 # 后内容当成值。注释必须独占一行。7. 知识库检索
6.1 终端直接检索
uv run a-share search "宁德时代固态电池" --top 5
uv run a-share search "政策" --source cls --sentiment positive
uv run a-share search "风险" --stock 001212 --min-importance 3
6.2 Python 检索 (带过滤)
from vectorstore import VectorStore, SearchFilter, make_qdrant_client
c = make_qdrant_client()
s = VectorStore(c)
hits = s.query(vector=probe["vector"], top_k=10,
filter=SearchFilter(source_id="cls", importance_min=3, sentiment="positive"))
for h in hits: print(h.short_summary())
s.close()
支持 8 种过滤: source_id / stock_codes / company_names / industries / sentiment / importance_min / event_types / date_range。
6.3 日报
uv run a-share report # 生成今日日报并上传
uv run a-share report --date 20260616 # 指定日期
uv run a-share report --no-upload # 仅生成不上传
HTML 日报含: AI 摘要 (LLM 生成 400-500 字要点) + 数据总览 + 情绪分布 + 事件类型 + 高重要度事件列表。
8. 定时任务部署
7.1 安装 systemd 服务 (一次性)
sudo cp scripts/a-share-research.service /etc/systemd/system/
sudo systemctl daemon-reload
sudo systemctl enable a-share-research
7.2 日常操作
| 启动 | sudo systemctl start a-share-research |
| 停止 | sudo systemctl stop a-share-research |
| 状态 | sudo systemctl status a-share-research |
| 实时日志 | journalctl -u a-share-research -f |
默认执行时间: 每天 07:00 / 12:00 / 18:00 / 22:00。7:00 的日报自动覆盖过去 24 小时新闻。
修改定时配置
# 1. 编辑 .env 中的 SCHEDULE_TIMES
nano /home/pi/news/.env
# 格式: HH:MM,HH:MM,... (24 小时制, 逗号分隔)
# 例: SCHEDULE_TIMES=08:00,14:00,20:00
# 2. 重启服务
sudo systemctl restart a-share-research
# 3. 验证
grep "已注册定时任务" /home/pi/news/logs/scheduler.log | tail -4
8. MCP 服务与 AI Agent
8.1 连接 Cherry Studio
设置 → MCP 服务器 → 添加:
{"mcpServers":{"a-share-research":{"command":"uv","args":["run","python","-m","scripts.run_mcp_server"],"cwd":"/home/pi/news"}}}
8.2 5 个 MCP 工具
| 工具 | 功能 | 示例 |
|---|---|---|
search_news | 通用语义检索 | search_news("宁德时代固态电池") |
search_company_news | 按公司检索 | search_company_news("价格", company="茅台") |
search_industry_news | 按行业检索 | search_industry_news("政策", industry="半导体") |
search_stock_events | 按股票代码检索 | search_stock_events("事件", stock_code="300750") |
search_sentiment_trend | 情绪检索+统计 | search_sentiment_trend("AI算力", sentiment="all") |
9. 投研分析模板
在 Cherry Studio 中粘贴 docs/agent_prompt.md 作为 System Prompt:
10. 附录
A. Qdrant 部署模式
| 本地文件模式 (默认) | Docker Server 模式 | |
|---|---|---|
| 类比 | SQLite | PostgreSQL |
| 进程 | 无独立进程 | 容器 a_share_qdrant |
| ARM64 | ✅ | ❌ jemalloc 16K 页崩溃 |
| 适用 | 树莓派 / 单机 | x86 生产 / 远程 |
B. 环境变量
LLM_PROVIDER | deepseek | M4 LLM |
DEEPSEEK_API_KEY | — | DeepSeek Key |
DASHSCOPE_API_KEY | — | 百炼 Key (M5/M8) |
EMBEDDING_PROVIDER | dashscope | M5 嵌入 |
SCHEDULE_TIMES | 07:00,12:00,18:00,22:00 | M7 定时 |
C. 日志文件
logs/crawler.log · logs/extractor.log · logs/dedup.log · logs/llm.log · logs/embedding.log · logs/qdrant.log · logs/scheduler.log · logs/mcp_server.log (自动轮转 10MB×5)
D. 常见问题
Q: 某源抓取 0 篇?
A: 编辑 configs/sources.yaml,检查 article_url_pattern 正则。或重新 discover 分析。
Q: LLM 报错?
A: 检查 .env 中 DEEPSEEK_API_KEY。可切换 --provider qwen 测试。
Q: Qdrant 搜索无结果?
A: uv run a-share status 检查数据量。若 Qdrant 为 0,执行 uv run a-share ingest --date <date> --recreate。
Q: 从零重建知识库?
rm -rf data/raw data/processed data/dedup data/deduped data/events data/embeddings data/qdrant_storage
uv run a-share pipeline --once