bigywater.tech
爬虫工程 · 26

robots.txt:规则匹配的优先级与 robotparser 的差异

遵守 robots.txt 是爬虫最基本的礼貌。但“遵守”的细节很多:Allow 与 Disallow 谁优先、通配符怎么算、UA 名字怎么匹配、robots.txt 本身打不开怎么办。这篇把标准库和 Scrapy 用的 protego 放在一起,用 26 个边界用例逐条对照,再看 HTTP 状态对 read() 的影响。

1 / 26
标准库与 protego 判断不同的用例数
Crawl-delay: 1.5
两个解析器都读成 None 的写法(整数可以)
5xx 全禁
robots.txt 返回 500 或 503 时,标准库 read() 之后整站不可抓

规则怎么匹配

实测 · 本机执行输出
  用例                                           标准库  protego  是否一致
  最长匹配:Allow 更长压过 Disallow                    True     True
  最长匹配:Disallow 写在 Allow 之后也一样                True     True
  长度相同的 Allow 与 Disallow                      True     True
  长度相同,Allow 写在前面                             True     True
  前缀匹配                                       False    False
  路径区分大小写                                     True     True
  通配符 * 在中间                                  False    False
  结尾 $ 精确匹配(.pdf 结尾)                         False    False
  结尾 $:路径后面还有查询串                              True     True
  空的 Disallow = 全部允许                          True     True
  Disallow: / 禁止整站                           False    False
  Disallow: / 之外 Allow: /ok                   True     True
  查询串匹配 /search?q=                           False    False
  百分号编码:规则写 ~,请求写 %7E                        False    False
  百分号编码:规则写 %7E,请求写 ~                        False    False
  UA 精确组 vs * 组                               True     True
  UA 名字带版本号 MyBot/1.0                        False    False
  组名是我的 UA 名字的子串("bot" 对 "MyBot")            False     True  ← 不一致
  组名比我的 UA 名字长("MyBotPro" 对 "MyBot")          True     True
  UA 名字大小写                                   False    False
  同一个 UA 出现在两个组里(是否合并)                       False    False
  多个 UA 共用一组                                 False    False
  规则之间的空行与注释                                 False    False
  字段名大小写与空格                                  False    False
  没有 User-agent 行的规则                          True     True
  robots.txt 本身                               True     True
  共 26 个用例,两者判断不同的有 1 个:['组名是我的 UA 名字的子串("bot" 对 "MyBot")']

两个解析器都按最长匹配决定 Allow 与 Disallow 谁优先(长度相同取 Allow),都支持 * 和结尾 $。路径区分大小写、前缀匹配、/robots.txt 自身总是允许。这是 Python 3.14.8 的标准库;更早版本的实现我没有测,不要把这里的结论套到旧版本上。

UA 名字与 Crawl-delay

实测 · 本机执行输出
  标准库:crawl_delay("MyBot") = 7,crawl_delay("Other") = 3,request_rate("Other") = RequestRate(requests=2, seconds=10),site_maps() = ['http://example.test/sitemap1.xml', 'http://example.test/sitemap2.xml']
  protego:crawl_delay("MyBot") = 7.0,crawl_delay("Other") = 3.0,request_rate("Other") = RequestRate(requests=2, seconds=10, start_time=None, end_time=None),sitemaps = ['http://example.test/sitemap1.xml', 'http://example.test/sitemap2.xml']
  Crawl-delay: 1.5 这种小数:标准库 = None,protego = None

组名 bot 对我的 UA MyBot:标准库认为适用(子串匹配),protego 不适用——这是 26 个用例里唯一的分歧。Crawl-delay 两者都能读取整数,Crawl-delay: 1.5 这样的小数两者都得到 None,所以不能靠它们表达小于 1 秒的间隔。

robots.txt 打不开

实测 · 本机执行输出
  robots.txt 返回 200:/x 允许=False,/y 允许=True;disallow_all=False,allow_all=False
  robots.txt 返回 404:/x 允许=True,/y 允许=True;disallow_all=False,allow_all=True
  robots.txt 返回 410:/x 允许=True,/y 允许=True;disallow_all=False,allow_all=True
  robots.txt 返回 401:/x 允许=False,/y 允许=False;disallow_all=True,allow_all=False
  robots.txt 返回 403:/x 允许=False,/y 允许=False;disallow_all=True,allow_all=False
  robots.txt 返回 429:/x 允许=True,/y 允许=True;disallow_all=False,allow_all=True
  robots.txt 返回 500:/x 允许=False,/y 允许=False;disallow_all=True,allow_all=False
  robots.txt 返回 503:/x 允许=False,/y 允许=False;disallow_all=True,allow_all=False
  robots.txt 返回 301:/x 允许=False,/y 允许=True;disallow_all=False,allow_all=False
  从没读过 robots.txt(没调用 read/parse):can_fetch = False

标准库 read():404、410、429 等 4xx 视为没有限制;401、403、500、503 视为整站禁止;重定向会被跟随。如果你的爬虫遇到 429(被限速)时把整站当“全部允许”,要意识到这是标准库的选择,不一定是你想要的。

分步演示

robots.txt
本步的对象

    本文用到的工具与边界

    • 本机 macOS 27 arm64 / Python 3.14.8 / requests 2.34.2 / aiohttp 3.14.3 / lxml 6.1.1(系统 Python);所有请求只发给本机自己起的测试服务器(127.0.0.1,端口 9960 以上,不访问任何真实网站);服务器可以按实验需要制造延迟、断连、压缩、重定向等行为,并记录收到的原始请求;计时用 time.perf_counter,数字每次运行会有小幅抖动。解析器:Python 3.14.8 标准库 urllib.robotparser,protego 0.7.0(pip 装进实验专用目录,实验后删除);用例都是纯文本解析(URL 是 example.test,不发请求);HTTP 状态实验用本机服务器按查询参数返回 200、301、404、410、401、403、429、500、503
    • 没有验证:RFC 9309 原文的要求(上文只描述两个实现的行为,没有逐条对照标准);Python 旧版本的 robotparser(印象里是按顺序第一条匹配且不支持通配符,没有测);Googlebot 等搜索引擎实际怎么解析;robots.txt 的大小上限、缓存时长;非 UTF-8 编码的 robots.txt;X-Robots-Tag 和 meta robots;不同解析器对畸形输入的处理
    京ICP备2026067502号-1京公网安备11010502063487号