Files
echart/quant/user_guide.html
simon 8ea9b48a9a feat: 投资资讯日报查询页 + 文档更新 + 拉取服务器最新内容
- 新增 charts/news_reports.php 报告查询导航页(列表+详情一体,fetch API 渲染)
- 新增 js/newsReports.js:AI 摘要/新闻联播/财经新闻/公告调研/数据总览固定模块,stats 归一化兼容多种格式
- index-2.php 研究报告卡片改为导航链接,移除 PHP 目录下拉框
- 更新 AGENTS.md/CLAUDE.md(路径、页面清单、数据模式等核实修正)
- 同步服务器拉取的文档:quant 使用手册、podcast-docs
- 生成 continuation.md 会话检查点
2026-08-05 20:28:57 +08:00

255 lines
15 KiB
HTML
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>A 股 Deep Research 用户手册 v1.1</title>
<style>
:root { --bg: #f8f9fa; --card: #fff; --text: #212529; --muted: #6c757d;
--accent: #2563eb; --border: #dee2e6; --code-bg: #f1f3f5; --radius: 8px; }
* { box-sizing: border-box; margin: 0; padding: 0; }
body { font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "PingFang SC", "Microsoft YaHei", sans-serif; background: var(--bg); color: var(--text); line-height: 1.75; padding-bottom: 4rem; }
.container { max-width: 900px; margin: 0 auto; padding: 1.5rem; }
header { background: linear-gradient(135deg, #1e293b, #334155); color: #fff; padding: 3rem 0 2rem; text-align: center; }
header h1 { font-size: 2rem; }
header p { color: #94a3b8; margin-top: .5rem; }
nav { background: var(--card); border-bottom: 1px solid var(--border); position: sticky; top: 0; z-index: 10; padding: .75rem 0; }
nav a { color: var(--accent); text-decoration: none; margin-right: 1rem; font-size: .9rem; }
h2 { font-size: 1.5rem; margin: 2.5rem 0 1rem; padding-bottom: .5rem; border-bottom: 2px solid var(--accent); }
h3 { font-size: 1.2rem; margin: 1.8rem 0 .8rem; color: #1e293b; }
h4 { font-size: 1rem; margin: 1.2rem 0 .5rem; }
p { margin: .6rem 0; }
a { color: var(--accent); }
code { background: var(--code-bg); padding: .15em .4em; border-radius: 4px; font-family: "SF Mono", "Fira Code", monospace; font-size: .88em; }
pre { background: #1e293b; color: #e2e8f0; padding: 1rem 1.2rem; border-radius: var(--radius); overflow-x: auto; font-size: .85em; line-height: 1.6; margin: .8rem 0; }
pre code { background: none; padding: 0; color: inherit; }
table { width: 100%; border-collapse: collapse; margin: 1rem 0; font-size: .93em; }
th, td { border: 1px solid var(--border); padding: .5rem .7rem; text-align: left; }
th { background: #f1f5f9; font-weight: 600; }
tr:nth-child(even) { background: #fafbfc; }
ul, ol { padding-left: 1.5rem; margin: .6rem 0; }
li { margin: .25rem 0; }
.card { background: var(--card); border: 1px solid var(--border); border-radius: var(--radius); padding: 1rem 1.5rem; margin: 1rem 0; }
.badge-ok { background: #d1fae5; color: #065f46; display: inline-block; padding: .1em .5em; border-radius: 10px; font-size: .8em; font-weight: 600; }
.badge-warn { background: #fef3c7; color: #92400e; display: inline-block; padding: .1em .5em; border-radius: 10px; font-size: .8em; }
.badge-err { background: #fee2e2; color: #991b1b; display: inline-block; padding: .1em .5em; border-radius: 10px; font-size: .8em; }
footer { text-align: center; color: var(--muted); font-size: .85em; margin-top: 3rem; padding-top: 1.5rem; border-top: 1px solid var(--border); }
@media (max-width: 640px) { .container { padding: .8rem; } header h1 { font-size: 1.5rem; } }
</style>
</head>
<body>
<header><div class="container"><h1>A 股 Deep Research 私有投研平台</h1><p>用户手册 v1.1 · 2026-06-17</p></div></header>
<nav><div class="container">
<a href="#概述">概述</a> <a href="#快速开始">快速开始</a> <a href="#cli">CLI 速查</a>
<a href="#全链路">全链路</a> <a href="#站点管理">站点管理</a> <a href="#检索">检索</a>
<a href="#定时任务">定时任务</a> <a href="#mcp">MCP</a> <a href="#投研">投研</a> <a href="#附录">附录</a>
</div></nav>
<main class="container">
<h2 id="概述">1. 项目概述</h2>
<p><strong>A 股 Deep Research</strong> 是私有化投研平台,自动完成财经新闻抓取 → 正文提取 → 事件抽取 → 向量化 → 语义检索,通过 MCP 协议接入 Cherry Studio / Claude Code,实现「自然语言提问 → 结构化研究报告」。</p>
<p><strong>技术栈</strong>: Python 3.11 · Crawl4AI · GNE · DeepSeek/Qwen · DashScope · Qdrant · APScheduler · MCP</p>
<p><strong>部署</strong>: 树莓派 5 (ARM64) <code>/home/pi/news/</code></p>
<h2 id="快速开始">2. 快速开始</h2>
<h3>2.1 安装</h3>
<pre><code>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 抓取需要</code></pre>
<h3>2.2 验证</h3>
<pre><code>uv run pytest -m "not integration" # 应显示 186 passed</code></pre>
<h2 id="cli">3. 统一 CLI 速查</h2>
<p>所有操作通过 <code>a-share</code> 命令完成。</p>
<table>
<tr><th>命令</th><th>功能</th><th>常用参数</th></tr>
<tr><td><code>a-share crawl</code></td><td>M1 抓取新闻</td><td><code>--source cls</code></td></tr>
<tr><td><code>a-share extract</code></td><td>M2 正文提取</td><td><code>--date 20260616</code></td></tr>
<tr><td><code>a-share dedup</code></td><td>M3 三层去重</td><td><code>--date 20260616 --reset</code></td></tr>
<tr><td><code>a-share events</code></td><td>M4 LLM 事件抽取</td><td><code>--provider qwen --limit 5</code></td></tr>
<tr><td><code>a-share embed</code></td><td>M5 向量化</td><td><code>--model text-embedding-v3</code></td></tr>
<tr><td><code>a-share ingest</code></td><td>M6 Qdrant 入库</td><td><code>--date 20260616 --recreate</code></td></tr>
<tr><td><code>a-share pipeline</code></td><td>全链路 (M1→M6)</td><td><code>--once --report</code></td></tr>
<tr><td><code>a-share discover</code></td><td>分析站点, 生成配置</td><td><code>--name 中文名 --add --extra URL</code></td></tr>
<tr><td><code>a-share add-entry</code></td><td>追加入口到已有源</td><td><code>source_id url1 url2 ...</code></td></tr>
<tr><td><code>a-share report</code></td><td>生成/上传日报</td><td><code>--date 20260616 --no-upload</code></td></tr>
<tr><td><code>a-share search</code></td><td>终端检索知识库</td><td><code>--source --stock --sentiment --top</code></td></tr>
<tr><td><code>a-share status</code></td><td>数据总览</td><td>无参数</td></tr>
</table>
<h2 id="全链路">4. 全链路一键运行</h2>
<pre><code>uv run a-share pipeline --once # 一次跑通 M1→M6
uv run a-share pipeline --once --report # 末尾自动生成日报并上传</code></pre>
<p>耗时约 4-5 分钟 (100 篇): crawler ~3min / extractor ~24s / dedup ~2s / llm ~45s / embedding ~10s / qdrant ~4s</p>
<p>只执行部分步骤: <code>uv run a-share pipeline --once --steps crawler,llm</code></p>
<p><strong>产物路径</strong>: <code>data/raw/</code> (M1) → <code>data/processed/</code> (M2) → <code>data/deduped/</code> (M3) → <code>data/events/</code> (M4) → <code>data/embeddings/</code> (M5) → <code>data/qdrant_storage/</code> (M6)</p>
<h2 id="站点管理">5. 新闻源管理</h2>
<h3>5.1 查看已有源</h3>
<p>配置文件: <code>configs/sources.yaml</code>。内置财联社 / 东方财富 / 新浪财经 / 证券时报 / 第一财经。</p>
<h3>5.2 新增站点 (一条命令)</h3>
<pre><code># 自动分析 + 写入 sources.yaml
uv run a-share discover https://example.com/news/ --name 中文名 --add
# 仅预览
uv run a-share discover https://example.com/news/</code></pre>
<p>自动完成: JS 抓取 → 链接提取 → 导航过滤 → 模式聚类 → 正则生成 → yaml 输出。写入时自动空行分隔、序号递增、<code># ---- N. 名称 ----</code> 注释头。</p>
<h3>5.3 同站多频道</h3>
<pre><code># 一次性分析多入口
uv run a-share discover https://example.com/news/global \
--extra https://example.com/news/china \
--extra https://example.com/news/tech \
--name 中文名 --add</code></pre>
<p>生成的 yaml 自动包含 <code>extra_homepages</code> 字段,抓取时依次访问所有入口,自动去重。</p>
<h3>5.4 为已有源追加入口</h3>
<pre><code>uv run a-share add-entry wallstreetcn https://xxx.com/news/新频道</code></pre>
<p>自动去重 — 已存在的 URL 跳过。</p>
<h3>5.5 验证</h3>
<pre><code>uv run a-share crawl --source wallstreetcn</code></pre>
<h2 id="cninfo">6. cninfo 公告抓取</h2>
<p>cninfo(巨潮资讯网)是独立的 A 股公告抓取管道,与新闻抓取分开调度(每天 08:00)。</p>
<pre><code>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 # 个股日报</code></pre>
<p>全链路 9 步: 公告→调研→IRM→提取→PDF→去重→LLM→向量→Qdrant。</p>
<h4>公告关注列表</h4>
<pre><code>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 # 只抓关注公司</code></pre>
<p>关注公司公告在日报中置顶并 ⭐ 高亮。配置: <code>configs/watchlist.yaml</code></p>
<p><strong>配置</strong>: <code>CNINFO_ENABLED</code> <code>CNINFO_DAYS_BACK</code> <code>CNINFO_MAX_PAGES</code> <code>CNINFO_API_BASE</code> <code>CNINFO_PDF_BASE</code></p>
<div class="card"><strong>⚠ .env 注意</strong>: 值后面不能跟 <code>#</code> 注释。python-dotenv 会把 <code>#</code> 后内容当成值。注释必须独占一行。</div>
<h2 id="检索">7. 知识库检索</h2>
<h3>6.1 终端直接检索</h3>
<pre><code>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</code></pre>
<h3>6.2 Python 检索 (带过滤)</h3>
<pre><code>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()</code></pre>
<p>支持 8 种过滤: source_id / stock_codes / company_names / industries / sentiment / importance_min / event_types / date_range。</p>
<h3>6.3 日报</h3>
<pre><code>uv run a-share report # 生成今日日报并上传
uv run a-share report --date 20260616 # 指定日期
uv run a-share report --no-upload # 仅生成不上传</code></pre>
<p>HTML 日报含: AI 摘要 (LLM 生成 400-500 字要点) + 数据总览 + 情绪分布 + 事件类型 + 高重要度事件列表。</p>
<h2 id="定时任务">8. 定时任务部署</h2>
<h3>7.1 安装 systemd 服务 (一次性)</h3>
<pre><code>sudo cp scripts/a-share-research.service /etc/systemd/system/
sudo systemctl daemon-reload
sudo systemctl enable a-share-research</code></pre>
<h3>7.2 日常操作</h3>
<table>
<tr><td>启动</td><td><code>sudo systemctl start a-share-research</code></td></tr>
<tr><td>停止</td><td><code>sudo systemctl stop a-share-research</code></td></tr>
<tr><td>状态</td><td><code>sudo systemctl status a-share-research</code></td></tr>
<tr><td>实时日志</td><td><code>journalctl -u a-share-research -f</code></td></tr>
</table>
<p>默认执行时间: 每天 07:00 / 12:00 / 18:00 / 22:00。7:00 的日报自动覆盖过去 24 小时新闻。</p>
<h4>修改定时配置</h4>
<pre><code># 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</code></pre>
<h2 id="mcp">8. MCP 服务与 AI Agent</h2>
<h3>8.1 连接 Cherry Studio</h3>
<p>设置 → MCP 服务器 → 添加:</p>
<pre><code>{"mcpServers":{"a-share-research":{"command":"uv","args":["run","python","-m","scripts.run_mcp_server"],"cwd":"/home/pi/news"}}}</code></pre>
<h3>8.2 5 个 MCP 工具</h3>
<table>
<tr><th>工具</th><th>功能</th><th>示例</th></tr>
<tr><td><code>search_news</code></td><td>通用语义检索</td><td><code>search_news("宁德时代固态电池")</code></td></tr>
<tr><td><code>search_company_news</code></td><td>按公司检索</td><td><code>search_company_news("价格", company="茅台")</code></td></tr>
<tr><td><code>search_industry_news</code></td><td>按行业检索</td><td><code>search_industry_news("政策", industry="半导体")</code></td></tr>
<tr><td><code>search_stock_events</code></td><td>按股票代码检索</td><td><code>search_stock_events("事件", stock_code="300750")</code></td></tr>
<tr><td><code>search_sentiment_trend</code></td><td>情绪检索+统计</td><td><code>search_sentiment_trend("AI算力", sentiment="all")</code></td></tr>
</table>
<h2 id="投研">9. 投研分析模板</h2>
<p>在 Cherry Studio 中粘贴 <code>docs/agent_prompt.md</code> 作为 System Prompt:</p>
<div class="card"><strong>公司分析</strong>: 分析宁德时代 (300750) 近 30 天的利好利空变化</div>
<div class="card"><strong>行业分析</strong>: 分析动力电池行业最近的政策动向和竞争格局</div>
<div class="card"><strong>风险排查</strong>: 梳理中旗新材 (001212) 近期面临的主要风险</div>
<div class="card"><strong>事件追踪</strong>: 过去一周 A 股有哪些重大监管处罚事件?</div>
<div class="card"><strong>情绪趋势</strong>: 近一个月 AI 算力概念的情绪变化趋势如何?</div>
<h2 id="附录">10. 附录</h2>
<h3>A. Qdrant 部署模式</h3>
<table>
<tr><th></th><th>本地文件模式 (默认)</th><th>Docker Server 模式</th></tr>
<tr><td>类比</td><td>SQLite</td><td>PostgreSQL</td></tr>
<tr><td>进程</td><td>无独立进程</td><td>容器 a_share_qdrant</td></tr>
<tr><td>ARM64</td><td><span class="badge-ok"></span></td><td><span class="badge-err"></span> jemalloc 16K 页崩溃</td></tr>
<tr><td>适用</td><td>树莓派 / 单机</td><td>x86 生产 / 远程</td></tr>
</table>
<h3>B. 环境变量</h3>
<table>
<tr><td><code>LLM_PROVIDER</code></td><td><code>deepseek</code></td><td>M4 LLM</td></tr>
<tr><td><code>DEEPSEEK_API_KEY</code></td><td></td><td>DeepSeek Key</td></tr>
<tr><td><code>DASHSCOPE_API_KEY</code></td><td></td><td>百炼 Key (M5/M8)</td></tr>
<tr><td><code>EMBEDDING_PROVIDER</code></td><td><code>dashscope</code></td><td>M5 嵌入</td></tr>
<tr><td><code>SCHEDULE_TIMES</code></td><td><code>07:00,12:00,18:00,22:00</code></td><td>M7 定时</td></tr>
</table>
<h3>C. 日志文件</h3>
<p><code>logs/crawler.log</code> · <code>logs/extractor.log</code> · <code>logs/dedup.log</code> · <code>logs/llm.log</code> · <code>logs/embedding.log</code> · <code>logs/qdrant.log</code> · <code>logs/scheduler.log</code> · <code>logs/mcp_server.log</code> (自动轮转 10MB×5)</p>
<h3>D. 常见问题</h3>
<div class="card"><h4>Q: 某源抓取 0 篇?</h4><p>A: 编辑 <code>configs/sources.yaml</code>,检查 <code>article_url_pattern</code> 正则。或重新 <code>discover</code> 分析。</p></div>
<div class="card"><h4>Q: LLM 报错?</h4><p>A: 检查 <code>.env</code><code>DEEPSEEK_API_KEY</code>。可切换 <code>--provider qwen</code> 测试。</p></div>
<div class="card"><h4>Q: Qdrant 搜索无结果?</h4><p>A: <code>uv run a-share status</code> 检查数据量。若 Qdrant 为 0,执行 <code>uv run a-share ingest --date &lt;date&gt; --recreate</code></p></div>
<div class="card"><h4>Q: 从零重建知识库?</h4><pre><code>rm -rf data/raw data/processed data/dedup data/deduped data/events data/embeddings data/qdrant_storage
uv run a-share pipeline --once</code></pre></div>
</main>
<footer><div class="container"><p>A 股 Deep Research 私有投研平台 · 用户手册 v1.1 · 2026-06-17</p></div></footer>
</body>
</html>