站点流量不大时,服务器对蜘蛛的抓取几乎无感。但当站内 URL 规模上去,或者某批页面突然被重新抓取,日志里就会出现集中的访问:响应时间从几十毫秒涨到几秒,偶尔冒出 500、502,数据库连接也接近打满。这时候容易走两个极端——要么随手把 UA 封掉,要么什么都不做硬扛。两种做法都不太划算。
先确认这确实是蜘蛛
很多所谓的抓取高峰其实是采集程序或扫描器,UA 里写着蜘蛛的名字。判断方法不复杂:看来源 IP 是否属于搜索引擎公布的地址段,看请求的 URL 分布是否符合站内结构,看它有没有请求 robots.txt 和 Sitemap。如果大量请求集中在搜索接口、登录页、导出接口上,基本可以确定不是正经蜘蛛。
确认真实之后,再看它抓的是哪些页面。多数情况下压力只来自少数几类:带参数的筛选页、站内搜索结果页、按日期归档的列表页。这些页面数量大、内容重复、每次都要查询数据库,是拖慢响应的高频来源。
缓存通常比任何限制都有效
蜘蛛请求的是同一批 URL,且不带登录态、不带个性化 Cookie,是缓存最理想的受众。把公开页面做成可缓存,命中率往往能上去一大截。
- 为公开页面设置合理的 Cache-Control,区分浏览器缓存和 CDN 缓存的时长;
- 对动态生成的列表页、详情页做整页缓存或片段缓存,注意只对未登录访客生效;
- 把图片、CSS、JS 交给缓存节点,避免每次抓取都回源;
- 检查缓存键里是否混进了多余参数,否则同一个页面会生成大量缓存副本,等于没缓存。
缓存生效后再看服务器响应时间,多数站点的瓶颈会明显后移。如果这时仍然吃紧,再考虑限速。
要限速,不要直接封禁
可以按来源 IP 设并发上限和每秒请求上限,超出后返回 429,并在 Retry-After 里给出建议等待时间。搜索引擎的抓取程序对这种信号通常有反应,会相应放慢节奏,而不是立刻放弃整个站点。
返回 429 或 503,只是让蜘蛛慢一点;返回 403 或者长期的空页面,等于告诉蜘蛛这个地址以后不用来了,两者的后果完全不同。
503 也可以配合 Retry-After 使用,适合整站维护或后端暂时不可用的场景。但要注意,5xx 持续出现会拉低蜘蛛对该站点的信任度,抓取频次可能被长期压低,想恢复比降下去更慢。
状态码要表达真实含义
- 200:内容正常返回。不要用它承载“系统繁忙”“请稍后再试”这类页面,那会变成软 404。
- 429:短时间请求过多,建议稍后再来。
- 503:服务暂时不可用,配合 Retry-After 使用。
- 403:明确拒绝访问,属于长期信号,慎用。
- 500:程序出错,蜘蛛会把它当成站点质量记录在案。
把压力场景下的返回码分清楚,比事后翻日志排查要省事得多。
从源头减少无意义的抓取
限流和缓存都是被动应对,更省资源的方式是减少蜘蛛去抓那些没有价值的 URL:
- 筛选参数页通过 robots.txt 或链接属性控制,避免组合爆炸;
- 站内搜索结果页、空结果页不要暴露给蜘蛛;
- 分页过深的列表页做收敛,不要一路翻到几百页;
- Sitemap 只放需要被发现的正式页面,不要把参数变体都塞进去。
需要被发现的 URL 数量少了,抓取量自然会下来,服务器压力也随之下降。
把监控做在事后之前
建议在日志里单独统计蜘蛛请求的数量、平均响应时间和状态码分布,按天看趋势。响应时间开始抬升、5xx 比例上升,都是可以提前发现的信号。等到抓取中断再回头查,成本会高很多。
服务器稳定与否,最终决定的是蜘蛛能不能持续、完整地读完站点。内容质量决定值不值得抓,稳定性决定抓得下来还是抓不下来。