本地优先的 sitemap.xml / robots.txt 生成与校验工具链
Local-first sitemap.xml & robots.txt generator & validator — zero third-party dependencies.
sitemapforge 是一款运行在你自己机器上的静态站点地图工具:它扫描构建产物目录(如 Hugo / Astro / VitePress / Next 导出目录、手写静态站),自动产出严格符合 sitemaps.org 0.9 协议 的 sitemap.xml、可选的 .gz 压缩版、TXT 清单与 robots.txt,并提供独立的协议校验器,让站点地图在部署前就做到零错误。
灵感来源:GitHub Trending 上 crawl4ai、open-seo 等「本地优先、替代云端 SaaS」的 Web 工具链持续走热。现有 sitemap 生成方案要么与特定框架绑定、要么依赖一串第三方包、要么需要把 URL 上传到云端,且很少有人认真实现 50,000 条 / 50 MiB 的自动分片与部署前协议校验。sitemapforge 只做这一件事,并把它做到开箱即用。
它解决的痛点:
- 😵💫 手写 sitemap 容易漏页、URL 风格不统一、忘记
lastmod; - 🔒 云端生成器需要上传站点结构,存在隐私与可用性顾虑;
- 🧩 框架插件方案迁移到另一套技术栈就要重学一遍;
- 📏 大站(>5 万 URL)需要 sitemap index 分片,手写几乎不可维护;
- ✅ 搜索引擎报错(无效
priority、错误日期、重复 URL)往往上线后才发现。
自研差异化亮点:
- 🧊 纯标准库、零三方运行时依赖,Python ≥ 3.8 即可,Windows / macOS / Linux 行为一致;
- 📴 完全离线、零遥测,URL 永远不离开你的机器;
- 📐 协议级严谨:自动按 50,000 条 / 50 MiB 分片并生成 sitemap index;
- 🔎 解析 HTML 元信息:canonical 覆盖、
meta robots=noindex自动剔除、hreflang多语言 alternate 自动输出; - 🕰️
lastmod三模式:文件mtime/git log提交时间 / 关闭; - 🧰 CLI + Python 库双形态,一条命令或三行代码均可使用;
- 🚦 校验器输出 error / warning 两级问题与 CI 友好退出码,直接接进流水线。
- 📁 目录递归发现:可配置页面后缀(默认
.html/.htm),自动跳过隐藏文件/目录; - 🎯 包含/排除规则:类 gitignore 的 glob(
404.html、/admin/*、draft/),支持白名单模式; - 🔗 URL 整形:pretty URL(
about/team.html→/about/team/)、尾斜杠开关、index.html → 目录根; - 📄 多制品输出:urlset XML、
sitemap.txt纯文本清单、.gz预压缩、sitemap index、JSON 构建报告; - 🤖 robots.txt 同发:多 User-agent 分组、Allow/Disallow/Crawl-delay、自动注入
Sitemap:指令; - 🌍 hreflang:读取
<link rel="alternate" hreflang>并输出xhtml:link; - 🧱 确定性输出:URL 排序、gzip mtime 固定,便于 diff 与缓存。
- 🧪 支持本地文件、
.gz、http(s) URL 三种来源; - 📏 检查数量上限(50,000)、体积上限(50 MiB 未压缩);
- 🧬 检查 XML 良构、根节点与命名空间、
<loc>必填且为合法 http(s) URL; - 🕰️
lastmod是否为 W3C ISO-8601(日期或带时区时间); - 🔁
changefreq枚举、priority数值区间 0.0–1.0、重复 URL 检测; - 📝 同时支持 urlset / sitemapindex / TXT 清单三种形态;
- 🚦 退出码:
0通过(允许 warning)、1存在 error、2用法/IO 错误。
| 项目 | 要求 |
|---|---|
| Python | 3.8 / 3.9 / 3.10 / 3.11 / 3.12(仅标准库) |
| 操作系统 | Windows、macOS、Linux 全平台 |
| 第三方依赖 | 零(wheel 安装无需联网下载任何传递依赖) |
| Git(可选) | 仅在 lastmod: "git" 模式下需要 |
# 方式一:PyPI 风格本地 wheel 安装(推荐)
pip install sitemapforge-1.0.0-py3-none-any.whl
# 方式二:克隆后可编辑安装
pip install -e .
# 方式三:免安装,直接在源码根目录运行
python -m sitemapforge --version# 1. 在当前目录生成一份带注释的配置模板
sitemapforge init
# 2. 扫描 dist/ 构建产物,生成 sitemap.xml 与 robots.txt
sitemapforge build -s ./dist -b https://www.example.com --gzip --txt
# 3. 部署前校验(也可以校验线上 URL)
sitemapforge validate ./dist/sitemap.xml
sitemapforge validate https://www.example.com/sitemap.xml运行后你会看到类似输出:
[sitemapforge] build summary
URLs included : 3
artifacts :
- sitemap.xml (838 B)
- sitemap.xml.gz (302 B)
- sitemap.txt (84 B)
- robots.txt (148 B)
public URLs :
- https://www.example.com/sitemap.xml
build OK
📸 运行截图 / 演示动图占位:可将终端录屏放在
docs/demo.svg并在此处引用。
| 命令 | 作用 | 常用参数 |
|---|---|---|
init |
写出配置模板 | -c 路径、-f/--force 覆盖 |
build |
扫描站点并生成制品 | -c 配置、-s 站点目录、-b 基础URL、-o 输出文件名、-d 输出目录、--lastmod {mtime,git,none}、--gzip/--no-gzip、--pretty/--no-pretty、--txt、--json-report、-q |
validate |
校验 sitemap | 来源路径或URL、--json |
{
"site_dir": "dist",
"base_url": "https://www.example.com",
"extensions": [".html", ".htm"],
"include": [],
"exclude": ["404.html", "*/draft/*", "/admin/*"],
"skip_hidden": true,
"pretty_urls": true,
"trailing_slash": true,
"lastmod": "mtime",
"default_changefreq": "weekly",
"default_priority": 0.5,
"changefreq_map": {"/": "daily", "/blog/*": "weekly"},
"priority_map": {"/": 1.0, "/about/*": 0.8},
"respect_noindex": true,
"use_canonical": true,
"collect_hreflang": true,
"out_file": "sitemap.xml",
"gzip": false,
"txt_sitemap": false,
"split_threshold": 50000,
"robots": {
"enabled": true,
"out_file": "robots.txt",
"rules": [
{"agent": "*", "allow": ["/"], "disallow": ["/admin/", "/*?preview="]}
]
},
"json_report": null
}| 字段 | 类型 | 说明 |
|---|---|---|
site_dir |
string | 构建产物目录,制品默认写入该目录 |
base_url |
string | 站点 origin,必填,自动补全 https://、去尾斜杠 |
extensions |
string[] | 参与发现的文件后缀 |
include / exclude |
string[] | glob 规则;include 非空时变为白名单;exclude 优先 |
pretty_urls |
bool | 去除页面后缀形成目录式 URL |
trailing_slash |
bool | pretty 模式下是否补尾斜杠 |
lastmod |
enum | mtime(默认)/ git(回退 mtime)/ none |
default_changefreq |
enum/null | always/hourly/daily/weekly/monthly/yearly/never |
default_priority |
float/null | 0.0–1.0 |
changefreq_map / priority_map |
object | 按 glob 路径覆盖默认值 |
respect_noindex |
bool | 自动剔除 <meta name="robots" content="noindex"> 页面 |
use_canonical |
bool | 用页内 canonical 作为 <loc>(外域 canonical 会被忽略并告警) |
collect_hreflang |
bool | 输出多语言 alternate |
split_threshold |
int | 单片 URL 上限(1–50000,协议硬顶 50000) |
gzip / txt_sitemap |
bool | 是否额外产出 .gz / .txt |
robots |
object | robots.txt 生成开关与规则 |
json_report |
string/null | 机器可读构建报告输出路径 |
from sitemapforge import Config, build_sitemap, validate_sitemap
cfg = Config.from_dict({
"site_dir": "./dist",
"base_url": "https://www.example.com",
"lastmod": "git",
"exclude": ["404.html"],
"gzip": True,
"robots": {"enabled": True, "rules": [
{"agent": "*", "allow": ["/"], "disallow": ["/admin/"]}
]},
})
result = build_sitemap(cfg)
print(result.included, result.output_sizes)
# 校验任意来源(本地 / gzip / URL)
report = validate_sitemap("./dist/sitemap.xml.gz")
assert report.ok, [(i.code, i.message) for i in report.errors]- 🏗️ 静态站构建流水线:构建后执行
build,把制品直接发布到托管平台根目录; - 🌐 多语言站点:页面内写好
hreflang,sitemap 自动携带 alternate; - 📚 超大文档站:无需关心分片,超过阈值自动产出
sitemap-partN.xml+ 索引; - 🧱 CI 守门:
validate以退出码阻断不合法 sitemap 合并; - 🔎 竞品/线上巡检:
validate https://.../sitemap.xml --json输出结构化结果。
- Q:提示 0 URLs? A:检查
site_dir是否正确、后缀是否在extensions内、是否被exclude/白名单过滤。 - Q:页面显示为
/page.html而不是/page/? A:开启pretty_urls(默认开),并按需设置trailing_slash。 - Q:git 模式没有拿到提交时间? A:确认站点目录位于 Git 工作区内;拿不到时自动回退到文件 mtime。
- Q:能在线爬取整站吗? A:本工具刻意保持本地优先,只扫描构建产物;在线爬取请使用爬虫类工具后再交给本工具格式化与校验。
- 标准库优先:XML 用
ElementTree/手写转义、压缩用gzip、下载用urllib——零供应链面,安装即所得; - 协议即边界:一切以 sitemaps.org 0.9 为准,50,000 / 50 MiB 是硬约束,不做“看起来能过”的模糊实现;
- 生成与校验分离:
build负责产出,validate可独立校验任何来源的 sitemap; - 确定性:排序、固定 gzip mtime,保证同一输入字节级可复现,利于 Git diff 与 CDN 缓存;
- CI First:所有结果都有退出码与 JSON 形态,方便无人值守。
- v1.1:RSS/Atom feed 发现并交叉提示;
news/image/videositemap 扩展命名空间 - v1.2:
lastmod支持内容哈希模式;HTML 内<url>与内链断链检测 - v1.3:增量构建(缓存上次结果,仅更新变化分片)
- v2.0:可选的本地预览服务器与 HTML 报告面板
- 🙋 社区贡献方向:更多配置预设(Hugo/Astro/VitePress)、更多输出格式、i18n 文档语种
本项目属于工具库 / CLI 类,无需下载可执行文件,三种集成交付方式:
# macOS / Linux 一键脚本(测试 + 打包 + 冒烟)
bash scripts/build.sh
# Windows PowerShell
powershell -ExecutionPolicy Bypass -File scripts/build.ps1产物为纯 Python 通用 wheel:dist/sitemapforge-1.0.0-py3-none-any.whl,可直接 pip install 或发布到私有源。
name: build-sitemap
on:
push:
branches: [main]
jobs:
sitemap:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with: { python-version: "3.12" }
- run: pip install sitemapforge
- run: sitemapforge build -c sitemapforge.json
- run: sitemapforge validate ./dist/sitemap.xml # 失败则阻断流水线
- uses: actions/upload-artifact@v4
with:
name: sitemap-artifacts
path: |
dist/sitemap.xml*
dist/robots.txt| 环境 | 状态 | 备注 |
|---|---|---|
| Python 3.8–3.12 | ✅ 支持 | 单元测试全绿 |
| Windows / macOS / Linux | ✅ 支持 | 路径统一按 POSIX 规则归一化 |
| 无网络环境 | ✅ 支持 | 仅 validate <URL> 需要网络 |
欢迎 Issue、PR 与文档翻译!流程与规范详见 CONTRIBUTING.md:
- 🍴 Fork 并从
main切出feat/xxx分支; - 💾 提交信息遵循 Angular Convention:
feat:/fix:/docs:/refactor:/test:/chore:; - 🧪 新增功能请同步补充
tests/单元测试,确保python -m unittest discover -s tests全绿; - 🔀 发起 PR,并描述动机、用法与测试方式。
本项目基于 MIT License 开源,可自由商用、修改与分发,保留版权声明即可。
⭐ 如果这个项目帮你省了时间,欢迎点 Star 支持:gitstq/sitemapforge