- 自动会话管理
- 锁定 195 个国家/地区的任意城市
- 无限并发会话
爬取延迟
简而言之:爬取延迟是爬虫向同一主机连续发送请求时,两次请求之间等待的时间。它以非官方 robots.txt 指令的形式声明,由爬虫在客户端执行。
爬取延迟用于控制请求节奏。延迟值为 5 表示爬虫完成一次请求后,会等待 5 秒再向该主机发送下一次请求。这项指令是礼貌爬取最直接的体现。由于服务器无法强制客户端等待,是否遵守该指令取决于爬虫自身。
robots.txt 指令:
User-agent: * Crawl-delay: 10 Disallow: /admin/ User-agent: MyCrawler Crawl-delay: 2 Disallow:
延迟值按用户代理组分别声明。标识为 MyCrawler 的爬虫需等待 2 秒,其他爬虫则需等待 10 秒。这项指令从未纳入最初的 robots.txt 规范,也不在 2022 年将该协议标准化的 RFC 9309 范围内。尽管如此,它仍被广泛使用。
爬虫支持情况:
| 爬虫 | 是否遵守 Crawl-delay | 说明 |
|---|---|---|
| Googlebot | 否 | 抓取频率可在 Search Console 中设置,也会自动调整 |
| Bingbot | 是 | 也可在 Bing Webmaster Tools 中配置 |
| Yandex | 是 | 有文档明确说明支持 |
| Scrapy | 是 | 通过 DOWNLOAD_DELAY 和 ROBOTSTXT_OBEY 实现 |
| 自定义爬虫 | 视实现而定 | 必须显式实现 |
Google 不支持这项指令是有意为之,并非疏漏。Googlebot 会根据观测到的服务器响应时间自行调整抓取频率,在延迟升高时放慢速度。其理由是,固定声明的数值无法反映服务器的实时状况。
如何选择延迟值:
| 目标网站类型 | 建议延迟 | 理由 |
|---|---|---|
| 大型商业网站 | 0.5–1 秒 | 基础设施完善,日常流量较高 |
| 中型网站 | 1–3 秒 | 承载能力适中,爬虫负载较为明显 |
| 小型或自行托管的网站 | 5–10 秒 | 资源有限,爬虫可能造成较大负载 |
| 已在 robots.txt 中声明 | 使用声明的数值 | 网站运营者已明确表达偏好 |
| 收到 429 响应后 | 遵循 Retry-After | 服务器已给出明确指令 |
延迟与爬取时长:
延迟会直接影响任务完成时间,而这种影响往往被低估。以 1 秒延迟顺序爬取 100,000 个页面,大约需要 28 小时;延迟为 5 秒时,耗时接近 6 天;延迟为 10 秒时,则接近 12 天。
因此,设置延迟时不能脱离整体爬取架构。兼顾礼貌爬取和吞吐量的方法,是跨主机并行,而不是对单个主机提高请求频率。例如,同时爬取 10,000 个域名,并对每台主机设置 1 秒延迟,就能获得较高的总体吞吐量,同时每台服务器每秒只会收到一个请求。
爬取延迟与速率限制的区别:
这两种机制经常被混淆。爬取延迟由客户端自行执行,属于自愿遵守:爬虫选择等待。速率限制则由服务器强制执行:服务器会拒绝超过阈值的请求,通常返回 429 请求过多。
爬虫可以忽略爬取延迟,却无法忽略速率限制,因为超出限制的请求会直接失败。遵守声明的延迟值,是爬虫避免触发强制速率限制的主要方式之一。
实现按主机设置延迟:
from collections import defaultdict
import time
next_allowed = defaultdict(float)
def fetch_with_delay(url, host, delay):
wait = next_allowed[host] - time.monotonic()
if wait > 0:
time.sleep(wait)
response = requests.get(url, timeout=10)
next_allowed[host] = time.monotonic() + delay
return response
为每台主机分别记录下次允许发送请求的时间,而不是每次请求后让整个爬虫等待,这样就能在等待某台主机时继续处理其他主机。这与 URL 待爬取队列中的后端队列层采用相同的原理。
Bright Data 的爬虫 API会自动读取并遵守已声明的爬取延迟,并在目标服务器出现负载压力迹象时调整请求节奏。