专项练习 · 9 分钟阅读

Python robots.txt 练习:规则、延迟与伦理

robots.txt 文件很小,影响却很大。这些练习解析常见指令,解释最长匹配优先级,并把文件放回“礼貌抓取或干脆不抓”的完整决策中。

解析指令

每个非注释行都是冒号分隔的键和值,键不区分大小写。只保存需要的值,但不要把这个小解析器当成完整的 robots 标准实现。

robots = '''User-agent: *
Disallow: /private
Allow: /private/public
Crawl-delay: 2'''
rules = {}
for line in robots.splitlines():
    line = line.strip()
    if not line or line.startswith("#") or ":" not in line:
        continue
    key, value = line.split(":", 1)
    rules[key.strip().lower()] = value.strip()
print(rules)

键、值与注释

采用最长匹配规则

Allow 和 Disallow 可能重叠。常见约定是最长匹配路径优先;长度相同时,更具体的规则通常获胜。不要看到第一行就停止判断。

rules = [("allow", "/private/public"), ("disallow", "/private")]
path = "/private/public/report"
decision = "allow"
best = -1
for kind, prefix in rules:
    if path.startswith(prefix) and len(prefix) > best:
        decision = kind
        best = len(prefix)
print(decision)

具体规则胜过宽泛规则

把延迟变成时间表

Crawl-delay 是请求间隔提示,不保证服务器健康。每次请求后记录时间戳,等到下一个允许时刻。如果站点在其他地方公布了更严格的限制,按更严格的执行。

from datetime import datetime, timedelta

start = datetime(2026, 1, 1, 12, 0, 0)
delay = 2
times = [start + timedelta(seconds=delay * i) for i in range(3)]
print([t.strftime("%H:%M:%S") for t in times])

有意识地拉开请求

遇到 429 就退让

429 表示请求过多。有 Retry-After 时读取它,至少等待那么久,并降低并发。立刻重试只会让问题更糟,甚至导致客户端被封禁。

status = 429
retry_after = "30"
if status == 429:
    wait = int(retry_after)
    print(f"wait {wait} seconds")
else:
    print("continue")

尊重服务器的回答

少收集,先询问

页面出现姓名、邮箱或健康信息,不代表可以收集。先定义最少字段,避免保存身份标识,不需要时删除原始页面。登录、验证码、付费墙和访问控制是边界,不是需要绕过的障碍。

record = {"name": "Ada", "email": "[email protected]", "bio": "Python"}
public = {key: value for key, value in record.items() if key != "email"}
print(public)

存储前先最小化

你的练习清单

常见问题

robots.txt 有法律约束力吗?

它是技术约定,不是完整法律协议。站点条款、版权、隐私法和合同可能增加更严格的义务。

没有 robots.txt 就可以随便抓吗?

不能自动视为授权。仍要查看条款并保持克制;文件缺失不是抓取全部内容的邀请。

小任务可以忽略 Crawl-delay 吗?

不要把任务小当作豁免理由。把延迟当作请求速率上限,服务器吃力时还要进一步退让。

练习 robots.txt 规则

12 道题,覆盖指令、最长匹配、延迟、429 处理和隐私。

打开练习

继续阅读: