# Requirements: 政务网站信息采集系统 (GovCrawler)

**Defined:** 2026-04-22
**Core Value:** 在不惊扰目标政务网站的前提下，稳定、增量、可追溯地把 20–30 个政务门户网站的公开内容持续落到本地存储，并让下游 RAG 系统简单地拉到增量。

## v1 Requirements

### Fetcher（抓取层）

- [ ] **FETCH-01**: 系统能通过 httpx 对无反爬站点做基础 HTTP 抓取（真实 UA + 超时 + 重试）
- [ ] **FETCH-02**: 系统能通过 Playwright + stealth 对强反爬站点（如 ctct 盾）执行浏览器抓取并自动通过 JS 挑战
- [ ] **FETCH-03**: 系统在 httpx 失败（非 200 或正文为空）时自动降级到 Playwright，Playwright 失败再降级到 DrissionPage
- [ ] **FETCH-04**: 系统维护 Cookie 池（Valkey，TTL 4h），同域名下浏览器过挑战后 Cookie 被后续 httpx 请求复用
- [ ] **FETCH-05**: 系统在单站连续 3 次 412/403 后放弃本轮抓取，不连续重试刺激对方 WAF

### Parser（解析层）

- [x] **PARSE-01
**: 系统支持按站点 YAML 配置使用 XPath/CSS 选择器抽取列表页的 URL、标题、发布时间
- [x] **PARSE-02
**: 系统支持按 XPath/CSS 选择器抽取详情页的标题、发布时间、发布主体、正文 HTML/文本、附件链接
- [x] **PARSE-03
**: 系统在 XPath 抽取失败或字段为空时自动用 GNE（通用新闻抽取）兜底抽取正文
- [x] **PARSE-04
**: 系统把详情页正文清洗为纯文本（去广告、去导航、保留段落结构）

### Scheduler（调度层）

- [ ] **SCHED-01**: 系统使用 APScheduler 按 Cron 定时触发每个栏目的抓取任务
- [ ] **SCHED-02**: 系统的默认调度策略为"每栏目每天 1 次、01:00–05:00 错峰"，允许 T+1 滞后
- [ ] **SCHED-03**: 系统对同一站点限制并发 ≤ 1、请求间隔 ≥ 5 秒、每次间隔加 ±20% 随机抖动
- [ ] **SCHED-04**: 系统支持手动触发单栏目抓取（CLI 或 REST API）用于调试与补抓

### Storage（存储层）

- [ ] **STORE-01**: 系统把原始 HTML 归档到本地目录 `/data/govcrawler/raw_html/<site>/<column>/<year>/<month>/`
- [ ] **STORE-02**: 系统把正文纯文本落盘到 `/data/govcrawler/articles_text/<site>/<column>/<year>/<month>/`
- [ ] **STORE-03**: 系统把附件原件落盘到 `/data/govcrawler/attachments/<site>/<column>/<year>/<month>/`，**不做任何解析/OCR/解压**
- [x] **STORE-04
**: 系统把元数据（含 url、url_hash、simhash、title、publish_time、source、category、text_path、raw_html_path、status、fetched_at、exported_to_rag_at）写入 PostgreSQL `articles` 表
- [x] **STORE-05
**: 系统把附件元数据（article_id、file_name、file_hash、size、file_path）写入 `attachments` 表，相同 hash 的附件去重不重复下载

### Incremental / Dedup（增量与去重）

- [ ] **INC-01**: 系统用 URL 归一化 + SHA256 作为去重键（`url_hash`），重复 URL 跳过不再抓取
- [ ] **INC-02**: 系统用正文 SimHash（64-bit）做语义级去重，相似度超阈值视为重复
- [ ] **INC-03**: 系统按栏目记录"最新文章时间戳"，下次跑批时遇到 ≤ 该时间戳的文章即停止翻页

### Config（配置层）

- [ ] **CFG-01**: 系统通过 YAML 文件定义站点（site_id、base_url、默认策略、并发、间隔）
- [ ] **CFG-02**: 系统通过 YAML 文件定义栏目（column_id、list_url、list_selector、pagination、detail selectors、category、schedule）
- [ ] **CFG-03**: 系统支持站点与栏目的 enabled 开关，可临时关闭某站点或栏目不影响其他
- [ ] **CFG-04**: 系统把 YAML 配置同步到 PG `sites`/`columns` 表，支持通过后台/SQL 热更新 XPath 不需重启服务

### API / RAG Interface（对外接口）

- [ ] **API-01**: 系统提供 `GET /api/articles?since=<ts>&site_id=<id>&limit=<n>` 增量拉取接口，返回未 ack 的新文章列表
- [ ] **API-02**: 系统提供 `GET /api/articles/{id}` 返回单篇完整元数据 + 正文文本
- [ ] **API-03**: 系统提供 `GET /api/articles/{id}/attachments/{aid}` 下载附件原件
- [ ] **API-04**: 系统提供 `POST /api/articles/{id}/ack` 让 RAG 侧标记"已消费"，回写 `exported_to_rag_at`

### Compliance / Low-Profile（合规与无感）

- [ ] **COMP-01**: 系统的 User-Agent 带明确身份与联系邮箱（如 `GovCrawlerBot/1.0 (contact: xxx@example.com)`）
- [ ] **COMP-02**: 系统默认遵守 robots.txt（可按站点配置豁免）
- [ ] **COMP-03**: 系统只抓取公开信息路径，不触碰 `/admin/`、`/api/internal/` 等非公开路径
- [ ] **COMP-04**: 系统所有运行时依赖的许可证均为 MIT / BSD / Apache-2.0 / PostgreSQL License / PSF，不引入 AGPL/SSPL/BSL/Elastic License 组件

### Observability（可观测性）

- [ ] **OBS-01**: 系统把每次抓取动作（站点、栏目、URL、策略、http_status、耗时、成功/失败、错误信息）写入 `crawl_logs` 表
- [ ] **OBS-02**: 系统暴露 Prometheus 指标：抓取成功率、耗时分布、412/403 率、浏览器启动次数、栏目新增文章数
- [ ] **OBS-03**: 系统在"单栏目成功率 < 80% 连续 2 轮"或"412/403 率 > 30% 持续 1 小时"时触发飞书/企微告警
- [ ] **OBS-04**: 系统在"栏目 24h 内无新文章且历史通常有更新"时告警（选择器失效信号）

### Deployment（部署）

- [ ] **DEP-01**: 系统支持通过 Docker Compose 单机部署（应用 + PostgreSQL + Valkey）
- [ ] **DEP-02**: 系统配置（站点 YAML、DB 连接、调度参数）通过环境变量 + 挂载目录注入，不硬编码
- [ ] **DEP-03**: 系统守护浏览器进程：单浏览器进程任务上限达到后自动重启，防止内存泄漏

## v2 Requirements

延后到 v2 或视需要再做，不列入本次 roadmap。

### Admin UI

- **ADMIN-01**: 管理后台提供站点/栏目 CRUD 与 XPath 在线编辑
- **ADMIN-02**: 管理后台提供运行监控面板（成功率、耗时、失败 Top N）
- **ADMIN-03**: 管理后台提供文章浏览、搜索、失败重放按钮
- **ADMIN-04**: 管理后台展示 RAG 对接状态（`exported_to_rag_at` 分布）

### Advanced

- **ADV-01**: Valkey Stream 事件推送（新增文章实时通知 RAG 侧）
- **ADV-02**: 选择器自愈（页面结构变化告警 + GNE 自动兜底切换）
- **ADV-03**: 支持 RSS/Atom 订阅源（Tier 1）

## Out of Scope

| Feature | Reason |
|---------|--------|
| 向量化 / Embedding / 切片 | 已有 RAG 系统负责，本系统只做采集与存储 |
| 附件内容解析 / OCR / PDF 抽文本 / ZIP 解压 | 下游系统处理，避免把复杂性塞进采集链路 |
| 登录态抓取 / 付费内容 | 只采公开信息 |
| 验证码破解 / 真滑块识别 | 触发即跳过；不采用打码平台 |
| 实时抓取 / 分钟级调度 | 允许 T+1 滞后；"无感"优先于"最新" |
| 代理 IP 池 | 20–30 站低频场景不需要；Cookie 池 + 频控已足够 |
| 分布式部署 / K8s | 单机 Docker Compose 对 20–30 站规模永久够用 |
| 在线全文检索 / 问答 UI | RAG 系统职责 |
| MinIO / S3 对象存储 | MinIO 是 AGPL；本地文件系统足够，避免传染性许可证 |
| Redis 7.4+ / Grafana / Loki / Elasticsearch | SSPL / AGPL / Elastic License 商用合规问题；改用 Valkey / 自建面板 / OpenObserve |

## Traceability

| Requirement | Phase | Status |
|-------------|-------|--------|
| FETCH-01 | Phase 2 | Pending |
| FETCH-02 | Phase 1 | Pending |
| FETCH-03 | Phase 2 | Pending |
| FETCH-04 | Phase 2 | Pending |
| FETCH-05 | Phase 2 | Pending |
| PARSE-01 | Phase 1 | Pending |
| PARSE-02 | Phase 1 | Pending |
| PARSE-03 | Phase 1 | Pending |
| PARSE-04 | Phase 1 | Pending |
| SCHED-01 | Phase 2 | Pending |
| SCHED-02 | Phase 2 | Pending |
| SCHED-03 | Phase 2 | Pending |
| SCHED-04 | Phase 2 | Pending |
| STORE-01 | Phase 1 | Pending |
| STORE-02 | Phase 1 | Pending |
| STORE-03 | Phase 1 | Pending |
| STORE-04 | Phase 1 | Pending |
| STORE-05 | Phase 1 | Pending |
| INC-01 | Phase 2 | Pending |
| INC-02 | Phase 2 | Pending |
| INC-03 | Phase 2 | Pending |
| CFG-01 | Phase 2 | Pending |
| CFG-02 | Phase 2 | Pending |
| CFG-03 | Phase 2 | Pending |
| CFG-04 | Phase 2 | Pending |
| API-01 | Phase 3 | Pending |
| API-02 | Phase 3 | Pending |
| API-03 | Phase 3 | Pending |
| API-04 | Phase 3 | Pending |
| COMP-01 | Phase 3 | Pending |
| COMP-02 | Phase 3 | Pending |
| COMP-03 | Phase 3 | Pending |
| COMP-04 | Phase 3 | Pending |
| OBS-01 | Phase 3 | Pending |
| OBS-02 | Phase 3 | Pending |
| OBS-03 | Phase 3 | Pending |
| OBS-04 | Phase 3 | Pending |
| DEP-01 | Phase 3 | Pending |
| DEP-02 | Phase 3 | Pending |
| DEP-03 | Phase 3 | Pending |

**Coverage:**
- v1 requirements: 36 total
- Mapped to phases: 36 ✓
- Unmapped: 0

**Per-phase totals:**
- Phase 1 (地基与 PoC 破冰): 10 requirements (FETCH-02, PARSE-01..04, STORE-01..05)
- Phase 2 (多站点采集内核): 15 requirements (FETCH-01/03/04/05, SCHED-01..04, INC-01..03, CFG-01..04)
- Phase 3 (RAG 对接与可运营化): 15 requirements (API-01..04, COMP-01..04, OBS-01..04, DEP-01..03)

---
*Requirements defined: 2026-04-22*
*Last updated: 2026-04-22 after roadmap creation*
