Files
bangwen/collectors/README.zh-CN.md
T
bitfennec 5a8af5729c docs: add bilingual README documentation for core and collectors
- Add English README.md and Chinese README.zh-CN.md for project root
- Enhance collectors/README.md and add Chinese collectors/README.zh-CN.md
- Document architecture, deployment, security invariants, and CLI/API usage
2026-10-24 00:00:50 +08:00

152 lines
5.4 KiB
Markdown
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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.
<a id="readme-top"></a>
# bangwen-collectors 边缘采集系统 🕷️
> **专为招考数据聚合设计的高性能、免代码声明式与 SSRF 安全强化的边缘抓取体系。**
---
## 📖 目录
- [✨ 概述](#-概述)
- [📁 目录结构](#-目录结构)
- [🚀 快速开始](#-快速开始)
- [环境准备](#环境准备)
- [本地安装](#本地安装)
- [🛠️ 采集器配置与开发指南](#️-采集器配置与开发指南)
- [免代码声明式 TOML 站点卡片](#免代码声明式-toml-站点卡片)
- [复杂场景 Python 定制适配器](#复杂场景-python-定制适配器)
- [⚙️ 调度策略与频控机制](#️-调度策略与频控机制)
- [🧪 测试与验证](#-测试与验证)
- [📜 开源协议](#-开源协议)
---
## ✨ 概述
`bangwen-collectors` 作为 `bangwen` 招考数据中枢的分布式边缘抽取层:
- **双模自动发现**:同时支持零代码声明式 TOML 站点配置卡片(`sources/`)与 Python 定制适配器(`adapters/`)。
- **按域名分组并发**:对不同域名并发抓取,而对相同域名严格排队串行,保障采集效率的同时彻底杜绝政务网 WAF 封锁。
- **礼貌延时与节流**:栏目间保持静默等待(默认 3.0s),单篇详情提取保留 0.3s 间隔微节流。
- **全链路 SSRF 纵深防护**:底层内置私有内网 IP 阻断、严格域名白名单匹配与 HTTP 重定向逐跳安全性校验。
---
## 📁 目录结构
```
collectors/
├── adapters/ # 针对复杂动态站点的 Python 专属抓取适配器
│ └── sc/chengdu_rsks.py # 成都人事考试网抓取适配器
├── sources/ # 零代码声明式 TOML 站点配置卡片
│ ├── sc/ # 四川省站点(如绵阳人事考试网、自贡人事考试网)
│ └── yn/ # 云南省站点(如云南人社厅、玉溪市人民政府)
├── common/ # 核心通用组件
│ ├── content.py # 脏正文清洗、超长文本截断与反爬标记识别
│ ├── declarative.py # 通用免代码声明式解析执行引擎
│ ├── fetcher.py # 支持 SSRF 逐跳校验与限速的 PoliteFetcher 客户端
│ ├── protocol.py # 与 bangwen/v1 摄入协议严格对齐的 Pydantic 模型
│ └── security.py # URL 白名单判定与内网 IP 阻断工具
├── tests/ # 安全防护与内容清洗回归测试集
├── config.toml # 采集调度与省份过滤总配置文件
├── runner.py # 多域名调度器与常驻运行入口
└── Dockerfile # 专属非 root 用户(UID 10001)容器镜像定义
```
---
## 🚀 快速开始
### 环境准备
- Python 3.12+
- [uv](https://docs.astral.sh/uv/) 包管理器
### 本地安装
1. **安装依赖**:
```bash
uv sync
```
2. **列出当前注册的所有采集渠道**:
```bash
uv run python runner.py --list
```
3. **执行一轮即时抓取与推流**:
```bash
uv run python runner.py --once
```
---
## 🛠️ 采集器配置与开发指南
### 免代码声明式 TOML 站点卡片
对于标准 HTML 结构的政务招考网站,只需在 `sources/{province}/{site_id}.toml` 编写配置,无需编写任何代码:
```toml
[site]
id = "yn.yuxi"
name = "玉溪市人民政府"
province = "云南省"
city = "玉溪市"
employer = "玉溪市相关用人单位"
employer_type = "事业单位"
allowed_domains = ["yuxi.gov.cn", "yxrc.cn"]
[template]
item_selector = "div.news-list a"
url_pattern = "/article/\\d+\\.html"
title_selector = "h1.article-title"
body_selector = "div.article-content"
date_regex = "(\\d{4}[-/年]\\d{1,2}[-/月]\\d{1,2})"
attachment_extensions = [".xlsx", ".xls", ".pdf", ".docx", ".doc", ".zip"]
[[channels]]
id = "rszk"
name = "人事招考"
start_url = "https://www.yuxi.gov.cn/rszk.html"
keywords = ["招聘", "考试", "录用", "公示"]
```
### 复杂场景 Python 定制适配器
对于含有复杂会话保持、加密参数或动态分页的站点,在 `adapters/{province}/{name}.py` 编写 Python 适配器:
- 实现抓取函数并返回符合标准的 `IngestPayload`。
- 强制使用 `common.security.is_safe_url` 实施外链与重定向安全隔离。
- 提取正文时使用 `common.content.sanitize_body_text` 剥离导航与脏文本。
---
## ⚙️ 调度策略与频控机制
调度器(`runner.py`)提供细粒度的运行控制:
| 环境变量 / 命令行参数 | 默认值 | 说明 |
|-----------------------|--------|------|
| `CORE_INGEST_URL` | `http://core:8080/api/v1/ingest` | Rust 核心网关的摄入接口地址 |
| `INGEST_TOKEN` | *空* | 与内核对齐的 HTTP Bearer 认证 Token |
| `SCHEDULE_INTERVAL_HOURS` | `6` | 常驻巡检的周期时间(小时) |
| `--provinces` | `[]` | 目标省份过滤(例如 `yn,sc`) |
| `--concurrency` | `3` | 跨域名的最大并发数 |
---
## 🧪 测试与验证
运行完备的本地安全回归套件(涵盖 SSRF 私网阻断、反爬脏正文过滤与附件扩展名判定):
```bash
uv run python tests/test_content_and_security.py
# 预期输出: All security and content tests passed!
```
---
## 📜 开源协议
本项目采用 [MIT](../LICENSE) 开源协议。
<p align="right">(<a href="#readme-top">回到顶部</a>)</p>