docs(data): 基本面语料库NAS采集设计spec§18+三摸底实测报告 [nas]——用户拍板六项范围(除公告PDF全量):新闻标题+摘要级/全文级/历史回补+公告元数据回补2000起/每日增量/定期业绩类PDF;硬约束=存储采集全NAS不上VPS(家宽IP与VPS东财限流零冲突)+采集限于00:30-17:30+慢爬;设计=1脚本corpus_download.py+1调度入口sanguo-corpus-daily 06:00(daily+backfill两lane串行,--until 17:30墙钟自停);数据模型=id键控(dt=发现日分区,无today文件名语义,天然免疫0902/0904式错标)+append-only短窗去重;回补顺序=公告meta→新闻meta→新闻全文→PDF(新→旧,容量闸门:/volume1实测645G空闲,每50GB自查,<200G暂停升级);失败语义吸收09-01/09-05教训(确定性错跳过不烧重试不连坐);探测优先能拿多深拿多深+depth_summary记录;附三摸底报告(聚宽136字段原料层≈100%已有/巨潮2000年起130万条年/东财3年硬顶/存储大头PDF 520G年) [nas]
CI/CD / test (push) Successful in 23s
CI/CD / nas-deploy (push) Successful in 0s
CI/CD / nas-verify (push) Successful in 8s

This commit is contained in:
2026-09-06 13:49:46 +08:00
parent 90b37ce27f
commit 92e63ee27c
2 changed files with 224 additions and 0 deletions
@@ -403,6 +403,127 @@ FETCHERS 注册表新增两键即自动可被未来 provider MCP server 暴露
- **VPS 部署终态**: 使用层 3 commit(4966d30/7f01c5f/564160d)推 VPS(run#1043,tag=564160d,
gap=0),VPS 端 8/8 功能验证过(双层接口/区间滤日/回补数据可读/白名单拒绝/实盘方法面)。
## 18. 增补 2026-09-06:基本面语料库(新闻+公告)采集设计——NAS 域(本节为最新,覆盖前文相关决策)
> 用户拍板(2026-09-06,经 factor session 转达):范围=六项全做(新闻标题+摘要级增量/新闻全文级/
> 新闻历史回补/公告元数据全量回补 2000 起/公告每日增量/定期+业绩类 PDF),**唯一不做=公告 PDF 全量
> (520GB/年)**。前置调研=`docs/fundamental_corpus_probes_20260906.md`(三摸底实测)。
> 本节为 spec,验收通过后才实施;spec 阶段零建表零采集。
### 18.1 硬约束(用户原话级)
1. **存储全部落 NAS、一律不上 VPS**——「vps承载有压力,之前基本面都放在了nas上,没有放vps,本次
也一样」。VPS 零参与:零 schtask、零存储、零采集进程;repo 里进脚本仅为随 NAS 部署管道分发
(promote --target nas → /app)VPS 侧永远不会被调度。
2. **采集发起位置=NAS 本机**(sanguo_vnpy_v2 容器内 docker exec)。关键差异:家宽出口 IP ≠ VPS
公网 IP(49.232.102.198),与 VPS 侧 ak-daily/ak-events 的东财限流**零冲突**——这正是采集放
NAS 的第二个理由(第一个是存储)。09-06 实测佐证:np-listapi/巨潮/东财文章页 ~35 发连续探测
自家宽 IP 全成功、零限流。
3. **时间带**:全部采集限于 **00:3017:30**,避开 18:0523:45 傍晚带(VPS 夜任务密集+家宽使用)。
唯一日窗=每日 06:00 起(见 18.3)。
4. 慢爬纪律:单进程单线程、per-domain 限速+抖动、直连不走代理(Session.trust_env=False,防
Mac 系统代理同款坑)。新浪线已判不可依赖(09-06 实测空返),本设计不使用。
### 18.2 数据模型(NAS 落位:/volume1/stock/corpus/,与 A股数据/ 平级)
```
/volume1/stock/corpus/
news_meta/dt=YYYY-MM-DD/part-0.parquet # 东财个股新闻·标题+摘要级(仅新条目,append-only)
news_fulltext/dt=YYYY-MM-DD/part-0.parquet# 东财新闻正文(按 art_code 全局去重,4.1KB/条)
ann_meta/dt=YYYY-MM-DD/part-0.parquet # 巨潮公告元数据(仅新条目;回补的也落发现日分区)
ann_pdf/YYYY/<announcementId>.pdf # 定期+业绩类 PDF(文件名=唯一id,天然幂等)
state/ # 断点水位+unit marker(JSON/parquet)
logs/corpus_YYYYMMDD_HHMMSS.log
```
Schema(列名冻结,消费方=factor session 因子加工层,后续 provider fetcher 可包):
- **news_meta**: `art_code`(pk), `stock_code`(6位), `show_time`, `title`, `summary`(可 null:
np-listapi 回补段无摘要——search-api 只有最近100条,历史摘要物理不存在), `media_name`(同上可
null), `url`, `first_seen_date`
- **news_fulltext**: `art_code`(pk,跨股票全局一条——同一篇稿提及多股只在 meta 层多行),
`url`, `show_time`, `content_text`(去标签正文), `fetch_date`
- **ann_meta**: `announcement_id`(pk), `sec_code`, `sec_name`, `org_id`, `title`, `short_title`,
`content`(摘要原文), `ann_time`(epoch ms→ts), `ann_type`, `ann_type_name`, `column_id`,
`important`, `adjunct_url`, `adjunct_size`, `batch_num`, `first_seen_date`
- **ann_pdf 索引**(state/ann_pdf_index.parquet): `announcement_id`, `sec_code`, `ann_type_name`,
`report_year`(从报告类别+公告年推), `local_path`, `bytes`, `fetch_date`
设计要点:**id 键控、无「$today 文件名」语义**——条目自带时间戳(show_time/ann_time),分区键是
发现日而非业务日,盘前跑/隔夜跑都无 0902/0904 式错标风险(与 A 档快照族的root差异)append-only
不重写(仅新条目入区,短窗 id 去重=读近 N 日分区),无 merge 改写类事故面。
### 18.3 采集设计:**1 个脚本 + 1 个调度入口**(脚本整合原则,用户追加指令②)
- **脚本**: `scripts/data_platform/corpus_download.py`(repo 内唯一新文件;单脚本红线同款——
corpus 栈一个入口,类型靠内部注册表,禁再开新脚本)。参数 `--lane daily|backfill`
`--until HH:MM`(墙钟自停)、`--limit N`(手动冒烟)。
- **调度**: DSM 任务计划 **sanguo-corpus-daily,每日 06:00 一条**:
`docker exec sanguo_vnpy_v2 python -X utf8 /app/scripts/data_platform/corpus_download.py
--lane daily && docker exec … --lane backfill --until 17:30`
(两 lane 串行同进程域=天然互斥;rc 聚合,任一 lane 失败 log 留痕)。回补 lane 每日从断点续跑,
17:30 前完成当前 unit 即 checkpoint 退出。
**daily lane(每日,总 ~4.5h,06:0010:30 前后)**:
1. 公告增量(巨潮,~5400 req @1/s≈1.5h):每股 seDate=T-1~T 两天窗+`announcement_id` 短窗去重
(同 margin_sse 两天窗自愈模式,漏一天次日自动补上);
2. 新闻增量(东财 search-api=akshare stock_news_em 同款端点,~5400 req @1/s≈1.5h):带摘要,
每股最近100条,新 art_code 入 news_meta;
3. 新闻全文(东财文章页,@2/s,~1万 req≈1.5h):仅下载昨日新发现的 art_code 正文;
4. 当日 PDF(定期+业绩类 category 过滤,数量级 ~100-400 份/日,峰值在 4 月年报季)。
**backfill lane(每日 10:3017:30 剩余时间,断点续跑,顺序=因子价值优先)**:
① ann_meta 全量回补(2000→今,unit=(stock,year),~19 万 req,预计 36 天跑完);
② news_meta 回补(np-listapi 标题级,unit=(stock,page),翻到空页或 page≥200 止,~11 万 req,
24 天)——历史段 summary=null 是物理上限(search-api 只有最近100条),spec 如实约定;
③ news_fulltext 回补(①②清单里的 url,@2/s,~1000万 req≈12 个月慢车道);
④ 定期+业绩类 PDF 回补(年份**新→旧**,2026→2000,~34 万份/~300GB,慢车道数周–数月)。
**容量闸门**: /volume1 实测空闲 645G(2026-09-06);PDF 回补每落 50GB 自查 `df`,空闲<200G 即
暂停 PDF 段并 log 告警升级用户重拍(其余段不受影响——非 PDF 段总盘子 <60G)。
**失败语义(吸收 09-01/09-05 教训)**: fetch 失败→unit 不标 done 不写半截(parquet tmp+rename);
真空(该股该年 0 公告)→标 done 合法;确定性解析错→记日志跳过该 unit **绝不烧重试、绝不连坐后续
unit**(northbound 断路器饿死教训);域名级连续传输错(403/429/超时×10)→该域本日冷却、它域继续、
rc=1 留痕,次日自然重试。
**探测优先(用户追加指令①)**: 深度不预设上限——巨潮按年翻到空、东财按页翻到空/PAGE 硬顶为止,
PDF 按可得性实下(404 标 missing 不重试);每源每股记录 first_date 入 state/depth_summary.json,
实施期边探边记,实际深度以落盘数据为准(三摸底测得:巨潮≈2000 起渐密/1993 有零星,东财≈最热股 3 年)。
### 18.4 预算汇总(实测口径)
| 层 | 增量/年 | 回补累计 | 请求量级 |
|---|---|---|---|
| news_meta(标题+摘要) | ~1.3GB | +3 年标题级 ~1.5GB | 日 ~5400;回补 ~11 万 |
| news_fulltext | ~10.6GB | 3 年 ~32GB | 日 ~1 万;回补 ~1000 万(慢) |
| ann_meta | ~1.3GB | 2000 起 ~15GB | 日 ~5400;回补 ~19 万 |
| ann_pdf(定期+业绩) | ~45GB | ~300GB(**带容量闸门**) | 日 ~100-400;回补 ~34 万 |
| **非 PDF 合计** | **~13GB/年** | **<60GB** | — |
### 18.5 验收标准(实施完成的定义)
1. **daily lane**: T+1 晨抽查 5 股(超热/热/中/冷/ST)——show_time/ann_time∈[T-1,T] 的条目
全在且 id 无重复;日志限速合规(平均间隔≥设定值,零 429/403 连击)。
2. **ann_meta 回补**: 600519 年报 2001 起逐年可查;announcement_id 全局无重;year×count 曲线
单调合理(早年稀疏→近年 ~130 万/年)。
3. **news 回补**: 600519 最早条目落 2023-09±1 月(实测硬顶对齐);depth_summary.json 全量产出。
4. **PDF**: 抽 20 份跨年份可打开(%PDF 魔数+size>0+meta 可反查路径);索引行数=文件数。
5. **边界**: /volume1/stock/corpus 之外零写入;VPS 零改动(git diff 触及面仅 scripts+tests+docs);
容量闸门演练一次(临时阈值)证明会停。
6. **测试**: tests/data_platform/ 新增 CI 测试(fetch 全 mock 零网络)——失败语义/短窗去重/
两天窗自愈/墙钟自停/unit marker,全套本地绿+CI 绿。
### 18.6 非目标(明确不做)
公告 PDF 全量(用户排除);因子加工层(factor session 职责,消费接口=18.2 的 parquet 契约);
新浪任何接口;VPS 侧任何东西;正文 NLP 解析/向量化;provider 出口(消费层稳定后再议,先直读
parquet);月度 compaction(数据量小,YAGNI)。
### 18.7 实施步骤概要(验收通过后,TDD)
T1 连通金丝雀(容器内 1 发/域+目录骨架)→ T2 corpus_download.py daily lane 四段+state 机制
+测试 → T3 DSM 任务注册+首周人工盯跑 → T4 backfill lane ①② → T5 ③④+容量闸门 → T6 验收
清单执行+活文档本节补「实施终态」小节。每步一个 commit,标签 **[nas]**(VPS 零触及)。
## 参考(调查来源)
- xtdata 官方:https://dict.thinktrader.net/nativeApi/xtdata.html