面向中国科学技术大学公开站点的本地归档与检索工具。它遵守 robots.txt,不使用账号凭据、不绕过登录或访问限制,并将抓取结果保存在本地 SQLite 和内容寻址文件中。
- 从学校主页、新闻网、职能部门和院系站点发现公开页面。
- 可断点续跑,并支持只刷新新闻列表和当前文章的增量更新。
- 解析标题、作者、发布时间、栏目、摘要、正文、图片和附件。
- 保存原始响应、结构化文章 bundle、图片源地址、媒体、附件和完整审计状态。
- 提供只读网页预览和 JSON API,区分新闻与通知。
- 对每个配置来源执行离线抽样,验证来源归属、原始文件、字段、bundle 和媒体。
config/ 来源配置
src/ustc_crawler/ 抓取、解析、存储、路由和网页预览
scripts/ 质量报告、在线覆盖检查和离线抽样验证
tests/ 单元与集成测试
data/ 本地运行数据,不提交 Git
模块职责和数据流见 ARCHITECTURE.md。
需要 Python 3.13 和 uv。
uv sync --locked
uv run ustc-crawler discover-ustc
# 小规模试跑
uv run ustc-crawler crawl \
--config config/sources.yaml \
--units data/discovered_units.json \
--include-units --include-supplemental \
--max-pages 200 --max-pages-per-source 20首次完整抓取:
uv run ustc-crawler crawl \
--config config/sources.yaml \
--units data/discovered_units.json \
--include-units --include-supplemental \
--max-pages 0 --max-depth 6169 个来源的增量更新:
uv run ustc-crawler crawl \
--config config/sources.yaml \
--units data/discovered_units.json \
--include-units --include-supplemental \
--incremental --max-depth 6 \
--concurrency 12 --delay 0.5--incremental 只刷新 seed、新闻列表/feed 和需要修复的文章页,并跳过已归档的空壳、重复页、导航页和课程资源。请求按主机限速;中断后重新执行同一命令即可续跑。
# 数据统计与导出
uv run ustc-crawler stats
uv run ustc-crawler export
uv run ustc-crawler report
# 每来源离线抽样验证
uv run python scripts/validate_source_samples.py
# 只读本地预览
uv run ustc-crawler serve预览默认地址为 http://127.0.0.1:8765/。主要 API:
/api/summary/api/news?type=news|notice/api/sources/api/article?url=...
改进 Markdown 图片规则后可以直接从已保存的文章 body_html 修复数据。正文 HTML
仍作为源归档保存,修复会从它生成使用 /api/publications/images/{sha256} 地址的 Markdown。
sha256 是图片绝对源地址 UTF-8 字节的 SHA-256。大归档可以用 URL 游标和条数分块,
每次完成一个分块后只为实际处理的 article 写入同步 outbox:
uv run ustc-crawler rebuild-markdown \
--source unit-math-ustc-edu-cn \
--limit 1000
# 将输出的 last_url 设为 LAST_ARTICLE_URL 后继续下一页:
uv run ustc-crawler rebuild-markdown \
--source unit-math-ustc-edu-cn \
--after-url "$LAST_ARTICLE_URL" \
--limit 1000rebuild-markdown --source 只处理所选来源的已保存文章;--limit 0 表示全部文章,
--after-url 是按 article URL 排序的独占游标。此命令只更新 body_markdown 和图片
源元数据,原始 HTML 与其它文章字段保持不变,并按实际 article URL 写入 outbox。
重复执行会复用已有 revision 事件。需要同时应用完整解析规则(例如分类或正文抽取)时,
再使用 reindex;它同样会按实际重建的 canonical article 直接入队,不使用页面游标
作为同步游标。只需要同步已经用新规则抓取的文章,或重试此前只完成重建而未入队的记录
时,可以运行 sync-backfill;它使用按文章 URL 排序的独立 --after-url 和 --limit:
uv run ustc-crawler sync-backfill \
--source unit-math-ustc-edu-cn \
--chunk-size 100同步客户端使用部署在爬虫机器上的服务密钥,不依赖任何个人账号或本地密钥环。服务器地址和服务密钥分别通过环境变量提供;密钥只在内存中用于发送 X-Publication-Ingestion-Secret 请求头,不会写入 SQLite、归档、命令参数、输出或日志:
export USTC_CRAWLER_SERVER=https://example.invalid
export USTC_CRAWLER_INGESTION_SECRET='set-this-in-the-machine-secret-store'
# 先把历史文章分块写入本地 outbox,不发起网络请求
uv run ustc-crawler sync-backfill \
--db data/crawler.sqlite --data-dir data --chunk-size 100
# 重试并上传已持久化的不可变批次
uv run ustc-crawler sync \
--db data/crawler.sqlite --data-dir data \
--object-concurrency 8 \
--batch-concurrency 1批次默认最多 50 篇、单次请求上限 100 篇且正文约 2 MiB,断点重跑使用同一批次和幂等键;上传对象先从本地内容寻址 spool 校验 SHA-256/大小,再按服务端返回的请求头上传。未配置服务密钥时命令会以安全错误码退出。
同一批次内的对象上传和完成确认默认使用最多 8 个受限工作线程,并按计划顺序验证结果;可通过 --object-concurrency 或 SyncOptions.object_concurrency 调整到 1 至 64。批次默认串行投递;可通过 --batch-concurrency 或 SyncOptions.batch_concurrency 调整到 1 至 16。批次始终由协调线程串行认领并持久化,只有已认领的不可变批次并行投递;已保存的重试批次全部完成后才会认领新批次。--max-batches 仍按本次运行认领的批次数精确限制。
data/ 完全排除在 Git 之外。主要内容包括:
crawler.sqlite:抓取状态、页面、文章、媒体和附件关系。pages/:按响应 SHA-256 保存的原始内容。articles/:按文章 URL 哈希保存的 JSON 和正文 HTML。media/、assets/:去重后的图片和公开附件。exports/:JSONL、来源报告和验证报告。discovered_units.json:从官方院系目录生成的来源候选。
仓库只包含代码和静态来源配置。数据库、网页内容、备份、日志及生成报告不会被提交。
uv run ruff check src tests scripts
uv run pytest -qGitHub Actions 使用锁定依赖执行相同检查。
- 只跟随配置允许域名中的 HTTP(S) 链接。
- 遵守
robots.txt,不提交登录凭据。 - 登录门槛、403、验证码和不可访问页面只记录状态,不尝试绕过。
- PDF、Office 等公开文件作为附件归档,不冒充 HTML 文章。