Files
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

5.4 KiB
Raw Permalink Blame History

bangwen-collectors 边缘采集系统 🕷️

专为招考数据聚合设计的高性能、免代码声明式与 SSRF 安全强化的边缘抓取体系。


📖 目录


✨ 概述

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 包管理器

本地安装

  1. 安装依赖:

    uv sync
    
  2. 列出当前注册的所有采集渠道:

    uv run python runner.py --list
    
  3. 执行一轮即时抓取与推流:

    uv run python runner.py --once
    

🛠️ 采集器配置与开发指南

免代码声明式 TOML 站点卡片

对于标准 HTML 结构的政务招考网站,只需在 sources/{province}/{site_id}.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 私网阻断、反爬脏正文过滤与附件扩展名判定):

uv run python tests/test_content_and_security.py
# 预期输出: All security and content tests passed!

📜 开源协议

本项目采用 MIT 开源协议。

(回到顶部)