Skip to content

Repository files navigation

Doc-Scraper: 通用离线文档抓取与转换系统

Doc-Scraper 是一个解耦化、可扩展的离线文档抓取与 HTML 转 Markdown 格式化系统。 支持双后端并发调度、令牌桶 QPS 限流、API 熔断自动降级、原子化断点续抓以及多格式索引解析。


核心特性

1. 核心功能解耦 (Decoupled Architecture)

  • 多引擎抓取:抽象统一 Fetcher 接口,内置 HttpxFetcher(HTTP 直接抓取)与 FirecrawlFetcher(CLI + JS 动态渲染)。
  • 可配置解析器:通过 ParserConfig 支持任意站点的 CSS 正文选择器、指定 class/id/tag DOM 节点剔除、正则二次文本清洗等。
  • 多格式索引与锚点去重EntryParser 支持解析多格式索引,并根据唯一页面 URL (base_url) 自动去重聚合,保持网页原汁原味的完整排版 Markdown,消除 Fragment 锚点拆分产生的碎片文件与多余子目录。

2. 状态机与可靠性保障 (State Machine & Reliability)

  • 生命周期状态机:任务经历 PENDING → QUEUED → FETCHING → PARSING → DONE / FAILED / WAITING
  • 指数退避重试:针对网络波动、429 限流、5xx 错误自动计算指数退避,区分不可重试错误。
  • 原子检查点 (Atomic Checkpoints):定时原子化(write -> rename)持久化已完成状态 _state.json,防止中断损害数据完整性。
  • 优雅关停 (Graceful Shutdown):捕获 SIGINT (Ctrl+C),优先完成正在执行的请求后退出,支持断点续抓。

3. 双后端并发协同与熔断 (Hybrid & Circuit Breaking)

  • 双协程组协同:Firecrawl 组(低 QPS / 额度控制)与 HTTP 组(高并发 / 免额度)同时消费全局统一任务队列。
  • 自动熔断降级:若 Firecrawl API 额度耗尽,触发熔断器(Circuit Breaker),Firecrawl 组自动退出,剩余所有任务由 HTTP 组接管。

项目架构

.
├── pyproject.toml                     # 项目构建与依赖配置
├── README.md                          # 项目文档
├── path.md                            # 示例入口文件
├── SKILL.md                           # AI Agent 接入技能定义
├── configs/                           # 解析器预设配置文件目录
│   ├── wechat_miniprogram.json        # 微信小程序文档解析预设
│   └── generic_article.json           # 通用文章/文档解析预设
├── src/
│   └── doc_scraper/                   # 核心 Python 包
│       ├── __init__.py
│       ├── cli.py                     # CLI 命令行接口与子命令入口
│       ├── config.py                  # 配置模型 (ParserConfig, SchedulerConfig)
│       ├── state.py                   # 状态机与持久化 (TaskState, PersistentState)
│       ├── entries.py                 # 入口索引文件解析器 (TXT, JSON, CSV)
│       ├── fetchers/                  # 抓取引擎模块
│       │   ├── base.py                # Fetcher 接口与 FetchResult 容器
│       │   ├── httpx_fetcher.py       # HTTP 直接抓取器
│       │   ├── firecrawl_fetcher.py   # Firecrawl CLI 抓取器
│       │   └── fallback_fetcher.py    # 降级编排器
│       ├── parsers/                   # 内容提取与转换模块
│       │   ├── content_parser.py      # DOM 选择器、节点清理与 Markdown 转换器
│       │   └── path_builder.py        # 目录层级映射与主页面文档生成
│       └── schedulers/                # 调度与控速模块
│           ├── rate_limiter.py        # 令牌桶 TokenBucket 限速器与退避策略
│           ├── base_scheduler.py      # 单后端调度器
│           └── hybrid_scheduler.py    # 双后端并发协同与熔断调度器
└── scrape_wxdoc.py                    # 兼容入口脚本

安装与运行

前置要求

  • Python >= 3.10
  • uv (推荐)

快速运行 (默认使用微信文档预设)

# 测试模式 (处理前 5 个 URL)
uv run scrape_wxdoc.py --test

# 全量并发抓取 (默认双后端协同)
uv run scrape_wxdoc.py

# 使用 HTTP 模式抓取
uv run scrape_wxdoc.py --backend httpx --concurrency 10 --qps 10

CLI 命令行说明

使用 doc-scraper 命令或 scrape_wxdoc.py 脚本:

doc-scraper [子命令] [选项]
#
uv run scrape_wxdoc.py [子命令] [选项]

1. run 子命令 (默认)

参数 默认值 说明
--path-file path.md 入口索引文件路径 (支持 .md, .txt, .json, .csv)
--output doc 输出 Markdown 文档根目录
--backend hybrid 抓取模式: hybrid(双后端协同), auto(串行降级), httpx(HTTP模式), firecrawl
--config None 解析器 JSON 配置文件路径
--selector #docContent 提取目标正文的 CSS 选择器
--delimiter - 标题层级路径分隔符 (例如 开发-指南-起步)
--concurrency 8 通用 / HTTP 协程组并发数
--qps 8.0 通用 / HTTP 协程组 QPS 限速
--firecrawl-concurrency 2 Hybrid 模式下 Firecrawl 协程组并发数
--firecrawl-qps 1.0 Hybrid 模式下 Firecrawl 协程组 QPS 限速
--test False 测试模式 (仅处理前 5 个页面)
--limit 0 限制处理页面数量 (0 = 不限)
--force False 强制重新抓取所有页面 (忽略历史记录)

2. init-config 子命令 (生成配置模板)

uv run scrape_wxdoc.py init-config -o site_config.json

3. status 子命令 (查看当前进度)

uv run scrape_wxdoc.py status --output doc

4. repair-links 子命令 (整理与清理碎片文档)

uv run scrape_wxdoc.py repair-links --output doc --path-file path.md

功能:清理目标文档目录中由于锚点拆分产生的多余碎片文件及空目录,仅保留完整网页的主 Markdown 文件。


自定义第三方文档配置

抓取其他网站时,配置对应的正文 CSS 选择器与节点清洗规则。

示例 1: 命令行参数抓取

uv run scrape_wxdoc.py \
  --path-file my_urls.json \
  --selector "article" \
  --delimiter "/" \
  --backend httpx

示例 2: 使用 JSON 配置文件抓取

创建 custom_config.json

{
  "selector": "main.article-content",
  "remove_classes": ["sidebar", "navigation", "ads"],
  "remove_ids": ["comments", "footer-banner"],
  "remove_tags": ["script", "style", "nav", "footer"],
  "clean_patterns": [
    "Edit on GitHub"
  ],
  "heading_style": "atx",
  "path_delimiter": "/"
}

执行抓取:

uv run scrape_wxdoc.py --config custom_config.json --path-file urls.csv

运维与后台运行

PYTHONUNBUFFERED=1 nohup uv run scrape_wxdoc.py --backend hybrid > scrape.log 2>&1 &
tail -f scrape.log

License

MIT License

About

通用高可用离线文档抓取与转换系统 (Generic High-Availability Documentation Scraper & Converter)

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages