最近有一批开源开发者开始留意到一个现象:自己的代码明明放在公开仓库里,却被无声无息地下载、清洗、送入大语言模型的训练管道。更尴尬的是,从许可证角度讲,很多开源项目并没有明确授权这种使用方式,但从技术角度讲,任何能公开访问的代码都挡不住全力抓取的爬虫。Sourcehut 这次更新服务条款,就是在这样的背景下,第一次把“代码托管平台与 LLM 训练数据”这个矛盾摆到了台面上。
这篇文章不打算复述一遍新闻,而是想跟读者一起拆开几层问题:Sourcehut 的条款调整到底改变了什么?它背后反映的 LLM 数据获取模式是什么?作为开发者,你在 GitHub、Sourcehut、自建 Git 仓库上如何判断自己的代码是否会被抓取,又能做哪些实际防护?我们会从概念、条款边界、Robots 协议、许可证、服务器配置、日志验证这几个角度给出可落地的方案,最后聊聊开源社区正在进行的许可证博弈。
1. Sourcehut 服务条款变更:一次对 LLM 抓取的公开表态
Sourcehut 是一个被很多极客开发者喜欢的代码托管与协作平台,它不像 GitHub 那样堆砌社交功能,而是强调极简、异步、命令行友好,核心服务包括 git/hg 仓库、邮件列表、问题跟踪、wiki 等。正因为它服务于一批对技术纯净度非常敏感的开发者,它更新服务条款、明确限制 LLM 抓取的动作,才格外有象征意义。
从公开信息看,这次变更的核心方向,是平台在条款中明确了“未经授权,不得将平台上的内容用于训练大规模语言模型或类似技术”。换言之,如果你是一个爬虫运营方,想通过抓取 Sourcehut 上的公共仓库来积累训练语料,平台不会再把这当作正当的公共数据访问,而是当作违反平台规则的行为。
这件事既不是个案,也不是突发新闻。过去一年里,GitHub、GitLab、Stack Overflow、Reddit 都面临过“内容是否可以被 AI 公司免费训练”的争论,态度各不相同。Sourcehut 的动作之所以值得写,是因为它是一个规模不大但用户特征极其鲜明的平台:用户多为开源维护者、隐私意识强、重视工具型产品的独立性。平台选择站在维护者一边,说明“代码不应默认成为训练语料”正在从小众声音变成主流共识。
但我们也要冷静:条款更新只是平台规则层面的表态,不解决技术执行问题。爬虫不遵守服务条款的情况非常普遍,条款也不能代替许可证对代码使用的法律约束。真正要回答的问题是:条款变更能挡住哪一层抓取?挡不住哪一层?开发者自己还有什么牌可以打?
2. LLM 训练数据与代码托管:为什么是开源平台?
要理解 Sourcehut 这次变更的意义,先要知道大语言模型的训练数据从哪里来。主流 LLM 的训练语料来源一般包括网页快照、书籍、维基百科、论坛、学术论文,以及公共代码仓库。
代码仓库之所以会成为香饽饽,原因很直接:代码是高质量的结构化文本,里面包含大量逻辑关系、函数命名、注释、错误处理模式和框架调用方式。训练模型如果缺乏代码语料,就难以生成像样的程序;如果只依赖 Stack Overflow 问答,又缺了真实项目里的完整性。所以“爬取 GitHub 公共仓库”或“爬取 GitLab、Sourcehut 公共仓库”成了很多数据团队的首选路径。
这里有一个长期存在的认知错位:很多人认为“既然是开源,就意味着可以自由使用”。但开源许可证允许的是复制、修改、分发,不必然包括“把代码吸收进模型的训练集并用模型输出近似代码”这一用途。更麻烦的是,很多项目的仓库里混杂着不同许可证的代码,甚至有些代码根本没有标注许可证,而爬虫不会关心这些细节。
于是,平台方成了第一道闸门。代码虽然是用户上传的,但平台掌握着服务器、访问日志和对外接口。如果平台愿意,它可以识别异常抓取、屏蔽特定 User-Agent、限制 API 频率,甚至把条款改成“禁止训练”。这就解释了为什么 Sourcehut 的条款变更意义重大:它不是为你提供一个技术盾牌,而是为平台拒绝抓取给出了合同依据。
当然,另一个现实是:很多爬虫使用分布式 IP、伪装浏览器 UA、甚至从搜索引擎缓存里拿数据,平台很难单靠技术手段识别。所以要真正保护代码,开发者需要把“平台条款 + 项目许可证 + 服务器规则”叠加起来,形成三道防线。
3. 条款、Robots 协议与许可证:理解三者的边界
很多开发者容易把“服务条款”“Robots.txt”“开源许可证”混为一谈,以为拒绝抓取只需要在网上发个声明。实际这三者的作用边界完全不同。
| 类型 | 作用对象 | 约束力 | 弱点 |
|---|---|---|---|
| 服务条款(ToS) | 平台与用户之间 | 合同约束用户,对第三方爬虫有限 | 爬虫不是用户,平台需要技术配合才能执行 |
| Robots.txt | 站点与合规爬虫之间 | 行业约定,非法律强制 | 恶意爬虫不遵守,需配合 IP 封禁等 |
| 开源许可证 | 版权授权范围 | 法律约束,但依赖维权成本 | 代码没许可证时,授权范围更模糊 |
| 自定义声明(README/NOTICE) | 公众视野 | 表达意愿,警示作用 | 无强制执行力,需要前两者配合 |
以 Sourcehut 为例,如果你的项目托管在 Sourcehut 上,Sourcehut 的新条款相当于在“你与 Sourcehut 之间”划了一条线:平台不会协助训练抓取,甚至可能对违规行为采取措施。但这条线很难直接约束一家利用境外服务器爬数据的公司。能不能约束,取决于平台是否愿意动用技术手段。
Robots.txt 的定位是给“讲规矩的爬虫”看的。OpenAI 的 GPTBot、Anthropic 的 ClaudeBot、Google 的 Google-Extended 等都在官方文档里表示会遵守 robots.txt。但对于像 Common Crawl 这类用来做大规模网页快照的爬虫,以及各种自研爬虫,遵守程度参差不齐。
许可证则是另一个维度。GPL、MIT、Apache 2.0 等传统许可证并没有明确回答“AI 训练能不能用代码”。所以新的“AI 训练受限”许可证正在出现,例如带有额外使用条款的“非 AI 训练”声明。但要注意,给现有项目临时加附属条款是危险操作:如果你不是项目唯一版权所有者,必须先获得所有贡献者的同意,否则许可证变更无效。
Sourcehut 的条款变更,本质上是在平台层补上了一个缺口。它告诉用户:平台会在合同层面支持你拒绝训练抓取。但剩下的工程实现,仍然需要你自己面对。
4. 开发者防护矩阵:平台层、站点层、项目层
既然条款只是第一步,下面给出一个三层防护矩阵。我们把“防止代码被 LLM 爬虫收集”拆成三个层:平台层、站点层、项目层。
平台层
平台层指的是你托管代码的网站。不同的平台对 LLM 爬虫的策略不同。Sourcehut 更新 ToS 后,如果有明显的爬虫行为,平台理论上可以采取封禁等措施。GitHub 目前有公开的 robots.txt,并且也屏蔽了部分 AI 爬虫,但它的默认策略并不保证所有公开仓库都免于训练。GitLab 支持私有仓库和可见性控制,但对于自建 GitLab,你完全可以自己配置 nginx 反向代理来拦截。
在这个层里,你能做的最基本动作是:尽量把非公开项目设为私有;阅读平台的条款和 robots.txt;关注平台公告中关于 AI 训练的政策。不要假设“公开仓库默认被保护”。
站点层
如果你有独立站点、静态博客、文档站点,或者自建的 Git 服务器,站点层是最灵活的一层。你可以通过robots.txt声明不想被哪些爬虫抓取,也可以通过 Web 服务器配置直接拒绝某些 User-Agent 的请求,还可以用日志分析来发现异常抓取。
对大多数开发者来说,比较现实的做法是:在项目文档站点和博客的根目录创建robots.txt,明确列出Disallow对应的 LLM 爬虫。
项目层
项目层是很多人最容易忽略的。即使平台和站点都没挡,项目本身也要有明确的授权声明。具体来说:
- 确保仓库包含
LICENSE文件,否则在法律上别人很难判断你的意图。 - 在
README.md或NOTICE中增加一段“关于 AI 训练的使用限制”,说明你是否允许代码被用于训练。 - 如果项目有多个贡献者,别试图单方面修改为“禁止 AI 训练”许可证,这会引发争议。更好的做法是新增附加条款,并请所有贡献者确认。
- 为仓库设置
.gitattributes和CONTRIBUTING说明,让未来的贡献者知道代码的用途边界。
三层防护的优先级是什么?如果只能做一件事,先把 License 和 README 声明写清楚。第二件事,如果控制着站点,配置 robots.txt。第三件事,如果可以,把平台上的可见性设为非公开(或者至少把敏感仓库私有化)。这个顺序是按照“法律清晰度 > 行业约定 > 平台政策”排的。
5. 完整示例:配置 Robots.txt 与 Nginx 拦截
下面以“阻止主流 LLM 爬虫”为目标,给出一整套可以直接套用的配置。虽然你不一定能控制 Sourcehut 根域的 robots.txt,但是这个配置可以用在你自己的 Git 服务器、文档站点、个人博客或任何能放静态文件的 Web 服务上。
5.1 项目根目录 robots.txt 示例
这里给出一个常见 LLM 爬虫的屏蔽列表。注意这个列表并不包含全部爬虫,需要根据你的访问日志持续更新。
# robots.txt User-agent: Googlebot Allow: / # OpenAI 爬虫 User-agent: GPTBot Disallow: / # Anthropic 爬虫 User-agent: ClaudeBot Disallow: / # Perplexity 爬虫 User-agent: PerplexityBot Disallow: / # Google AI 训练扩展 User-agent: Google-Extended Disallow: / # CCBot(Common Crawl) User-agent: CCBot Disallow: / # 其他常见 AI 爬虫 User-agent: anthropic-ai Disallow: / User-agent: Bytespider Disallow: / User-agent: Amazonbot Disallow: /参数说明:
User-agent是爬虫在请求头里自报的名字。Disallow: /表示整个站点都不允许该爬虫访问。Allow: /可以根据你希望搜索引擎正常收录来保留。- 不是所有爬虫都会遵守 robots.txt,但主流公司级爬虫大多会尊重这一协议。
5.2 Nginx 反向代理屏蔽 User-Agent
如果你的代码托管服务或网站跑在 Nginx 后面,可以在server块中直接拒绝这些 UA。这种方式比 robots.txt 更强硬,因为请求根本不会进入后端应用。
# 文件路径:/etc/nginx/sites-available/mysite.conf server { listen 80; server_name git.example.com; # 禁止 LLM 相关爬虫访问 if ($http_user_agent ~* "(GPTBot|ClaudeBot|PerplexityBot|Google-Extended|CCBot|Bytespider|Amazonbot)") { return 403; } location / { proxy_pass http://127.0.0.1:8080; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; } }注意:Nginx 的if指令在某些场景下会被好心人劝退,但对于简单的 UA 拦截足够用。更严谨的写法是使用map模块,但对于入门配置,这个示例已经能跑通。
5.3 用 curl 验证你的 robots.txt
配置完成后,先别急着干别的。用 curl 看你的站点返回内容,确认文件正常。
# 查看 robots.txt 内容 curl -s https://git.example.com/robots.txt # 查看响应头,确认状态码 curl -I https://git.example.com/robots.txt # 模拟 GPTBot 请求首页,预期返回 403 curl -A "GPTBot/1.0" -I https://git.example.com/第一条命令应该输出你写的 robots.txt 内容。第二条命令状态码应为 200。第三条命令如果 Nginx 配了拦截,应该返回 403;如果没配,会返回 200,说明拦截规则没有生效。
5.4 日志分析:找出谁在爬你的代码
只配置不观察,等于没配置。如果你的 Web 服务器有 access log,可以用一行命令统计有哪些 User-Agent 出现得特别频繁。
# 从 access.log 中统计出现最多的 UA awk '{print $7}' /var/log/nginx/access.log \ | sort | uniq -c | sort -nr | head -20这里的$7对应的是 Nginx 默认日志中 User-Agent 所在位置,不同格式可能需要调整。如果你发现一些不在屏蔽列表里的可疑 UA,可以把它们加进 robots.txt 和 Nginx 配置。
6. 验证与观察:确认你的策略是否生效
很多开发者配置完 robots.txt 就以为万事大吉,实际上要验证“是否生效”需要做三件事。
第一,检查 robots.txt 的可达性。如果站点是 HTTPS,且使用了 CDN,直接用 curl 测试你是否能看到最新内容。有些 CDN 会缓存 robots.txt,导致爬虫看到的还是旧版本,所以清理 CDN 缓存也是一部分。
第二,模拟真实爬虫的请求。上面的 curl 模拟是一种方式,更接近真实的做法是直接查询公开的爬虫 UA 索引。比如 OpenAI 的官方文档会说明 GPTBot 如何发现并遵守 robots.txt,你可以尝试用 GPTBot 的 UA 访问自己的站点,并观察返回码。但注意,除非你控制请求源头,否则模拟请求不会真正进入 GPTBot 的爬虫队列。
第三,观察一段时间内的 access.log。真正的爬虫会在几天内持续出现。你可以记录基线,然后定期跑一次统计脚本,看新增的 UA 是否被挡住。如果某个爬虫的请求状态是 403,说明拦截生效;如果全是 200,说明 robots.txt 没有被它当回事,你需要升级到 Nginx 拦截或加 IP 限制。
从实际操作看,判断策略生效的优先级是:先确认 robots.txt 返回 200 且内容正确,再确认已知爬虫 UA 被服务器拒绝,最后再根据日志持续调优。
7. 常见问题与排查思路
| 问题现象 | 可能原因 | 排查方式 | 解决方案 |
|---|---|---|---|
| curl 能看到 robots.txt,但 GPTBot 仍然抓取 | robots.txt 对恶意爬虫没有强制力 | 查日志确认 GPTBot UA 是否出现 | 升级为 Nginx 拦截或防火墙封禁 IP |
| Nginx 拦截规则不生效 | if配置放在错误位置或正则未匹配 | 检查 nginx -t 并测试带 UA 请求 | 调整正则,或改用 map 模块 |
| 代码已经修改为“禁止 AI 训练”声明,但版本库历史仍可被抓取 | 旧提交可能通过 Git 协议暴露 | 查看平台是否提供仓库流量日志 | 将仓库转为私有,或使用 Git LFS 管理敏感历史 |
| Sourcehut 条款更新,但项目托管在 Sourcehut 上无人执行 | 条款只能管平台用户,管不了外面爬虫 | 用 GitHub/GitLab 做镜像时观察访问来源 | 联系平台客服报告异常行为 |
| robots.txt 屏蔽过多,导致搜索引擎收录下降 | 误将 Googlebot 也 Disallow 了 | 使用 Google Search Console 检查抓取 | 在User-agent: Googlebot下放行 |
| 团队多维护者,有人不同意“禁止 AI 训练”授权 | 许可证变更需要所有贡献者同意 | 检查项目 CONTRIBUTORS 列表 | 新增AI.md作为附加说明,避免改正式许可证 |
| 部署了 CDN 后 robots.txt 总不更新 | CDN 缓存了旧的 robots.txt | 查看 CDN 缓存状态头 | 强制刷新缓存,设置更短的 TTL |
如果遇到“配置了但仍然有人抓”的问题,请先确认你不是在和一个“遵守 robots.txt 的爬虫”打交道。真正让人头疼的是那些不遵守协议的爬虫,这时唯一可靠的手段是限制访问频率、封禁 IP、或者干脆把仓库设为私有。
8. 开源社区的博弈:从 ToS 到许可证运动
Sourcehut 的条款更新并不是孤例。它背后是开源社区对“AI 训练是否属于开源许可用途”的重新定义。
传统开源许可证的出现,是为了保护用户自由使用、修改、分发软件的权利。但在 LLM 时代,代码不再只是运行软件,它也是训练模型的原料。一个接受了大量开源代码训练的模型,在输出结果时可能“魔法”般复现原代码片段。这种情况下,原作者的署名和许可证要求是否应该跟着代码一起在模型参数里传播?答案远没有定论。
于是,社区正在自发地出现多种方案。有人在 README 里写“This project is not for AI training”;有人给现有项目附加“训练数据限制条款”;也有人转向更保守的自托管方案,比如把仓库放在 Sourcehut 自定义域名后面,并在站点层屏蔽爬虫。
这些努力的实际效果如何?从短期看,零散声明很难阻挡工业级数据采集。但从长期看,它们正在重塑行业规则:如果一个足够大的开发者群体集体表达“禁止训练”,AI 公司为了规避法律风险,就不得不把“来源筛选”和“许可证合规”纳入训练流程。Sourcehut 的服务条款转变,就是这个集体表达中的重要一环。
对开发者来说,这个话题不是“管好自己就行”。它还关系到你贡献的开源生态会不会变成无偿的数据矿场。我建议你把它当作一个工程合规问题来对待:给你的每一个项目补上 LICENSE,在 README 里说清楚 AI 训练边界,在站点日志里做监控,而不是只在社交媒体上抱怨。
9. 总结与后续学习方向
这篇文章从一个具体事件出发,拆开了 LLM 爬虫、服务条款、robots.txt、许可证之间的复杂关系。现在可以做几个清晰收束:
- Sourcehut 更新 ToS 表明代码托管平台开始回应 LLM 训练抓取问题,但它的效果要依赖平台是否愿意进行技术执行。
- Robots.txt 是行业约定,适合拦截尊重协议的爬虫;Nginx 配置和防火墙适合拦截不守规矩的爬虫;许可证和 README 声明是法律与意图的锚点。
- 你可以立即做的事:为项目补 LICENSE、在文档站点放 robots.txt、在服务器层拦截已知爬虫 UA、用 access.log 监控异常抓取。
- 更进一步研究的方向包括:各类 AI 训练许可证的兼容性、如何用 Git 钩子限制对历史提交的访问、如何在自有 Git 服务中实现按用户限流,以及如何与平台方报告爬虫滥用。
如果你正在维护一个开源项目,别等着平台替你挡住所有爬虫。把“代码是否允许被 AI 训练”变成一个显式决策,写进项目文档和配置里,才是当下最稳妥的工程实践。