system-design-notes:爬取频率怎么定?页面重要性×变化率的调度公式全解
【免费下载链接】system-design-notesNotes of the book System Desgin Interview - An Insider's Guide项目地址: https://gitcode.com/GitHub_Trending/sy/system-design-notes
在构建网页爬虫系统时,爬取频率是调度层最核心的问题:爬虫该多久重新访问一个页面?定得太勤,服务器被打爆、带宽被浪费;定得太慢,索引内容过期、搜索体验下降。本文基于 system-design-notes 项目中第 9 章 09. Web Crawler/Readme.md 的设计,讲清"页面重要性 × 变化率"这一爬虫爬取频率调度公式的完整推导与落地方式。

先搞清楚:爬虫为什么需要"爬取频率"调度?
一个搜索级爬虫的典型目标是:每月爬取 10 亿页面,即平均约 400 页/秒、峰值 800 QPS。面对十亿级存量页面,"多久重爬一次"直接决定了两件事:
| 决策倾向 | 后果 |
|---|---|
| 频率过高 | 目标服务器被打挂(不礼貌)、带宽与存储成本激增 |
| 频率过低 | 索引内容陈旧(freshness 差),用户搜不到最新内容 |
所以调度器必须回答一个量化问题:下一次爬这个 URL,应该等 T 天?而 T 由两个因子共同决定——页面的重要性和页面的变化率。
调度公式拆解:重要性 × 变化率
书中给出的思路(见 09. Web Crawler/Readme.md)可以归纳为一个调度公式:
调度得分 S = 页面重要性 P × 新鲜度缺口 (1 − F)重爬间隔 T ≈ T_base ÷ S
三个变量各有来源:
- 页面重要性 P(Priority):可用 PageRank 类指标衡量。被大量高权重页面指向的页面,值得更频繁地爬取。书中明确指出"为重要页面(如按 PageRank 或更新频率衡量)赋予更高优先级"。
- 新鲜度 F(Freshness):记录该 URL 的历史更新频率。一个页面如果连续 10 次重爬内容哈希都没变(内容去重靠 Content Seen? 组件对比哈希值),说明它是"死页面",间隔可以拉长到数周甚至数月。
- T_base:全局基准间隔,由总 QPS 预算反推(下一节估算)。
这样得到的效果是:首页、新闻页(高重要性、高变化率)每天甚至每小时重爬;个人博客归档页(低重要性、低变化率)几个月爬一次。频率资源自动向最有价值的流量倾斜。

用二幂法则估算 QPS 预算,反推基准间隔
T_base 不是拍脑袋定的,而是容量估算的产物。项目第 2 章 02. Back Of the Envelope Estimation/Readme.md 教我们用"二幂表"快速估算数量级:

以 10 亿页/月为例:
- 月 → 秒:
10⁹ ÷ (30 × 86400) ≈ 10⁹ ÷ 2.6×10⁶ ≈ 400 QPS(平均) - 峰值通常取平均的 2 倍:800 QPS
- 假设全网 100 亿存量 URL、平均每月需要重爬 20% 的页面,则调度器每月需派发 20 亿次任务 → 调度层自身只需约0.7 次/秒的"插入 frontier"速度,完全可行。
结论:重爬总预算固定,调度公式的作用是在预算内做最优分配,而不是无限加频率。
频率的另一半:礼貌性限流(Politeness)
再高的优先级也不能突破礼貌约束。书中 09. Web Crawler/Readme.md 的 Politeness 机制把"同一时刻每个 host 只发一个请求"做进了队列结构:

关键设计是三层结构:
- Queue router:按 hostname 把 URL 路由进同一主机的队列,保证同一站点不会被并发轰炸
- Mapping Table:主机 → 队列的映射
- Worker thread + 下载延时:每个工作线程串行处理一个主机的队列,两次下载任务之间插入 delay
这套机制本质上是一种按主机维度的限速器。如果你熟悉限流算法,它就是令牌桶的按 host 分桶版本——类似项目 04. Rate Limiter/Readme.md 中讲的令牌桶思想:每个 host 一个桶,令牌补充速率就是该站点的允许爬取频率。

优先级调度与礼貌限流最终合二为一:front 队列管优先级(谁先爬),back 队列管礼貌性(对谁温和),两者串联后 URL 才能真正交给 HTML Downloader。
调度器怎么落地?两级队列 + 可扩展模块
把公式落到工程上,书中推荐的做法(09. Web Crawler/Readme.md)是:
- Prioritizer:对每个新 URL 计算 S 值,写入对应优先级的 front 队列 f1…fn
- Front queue selector:按优先级加权随机选择队列输出 URL——高优先级队列被选中的概率更高
- Back queue router:再按主机维度二次分队列,交给 Worker 线程
- Freshness 反馈闭环:每次爬完,Content Seen? 组件对比新旧内容哈希,把"是否变化"写回该 URL 的元数据,供下一轮调度计算 F 使用
这就是完整的调度闭环:爬取 → 内容哈希比对 → 更新变化率统计 → 调整下一次间隔。

顺带一提,调度策略本身也可以是可插拔模块。当监控版权、监控价格波动等不同"变化率信号"出现时,只需替换 Prioritizer 的评分函数,流水线无需改动——这正是第 9 章强调的 Extensibility 设计目标。
新手常见误区清单
- ❌全站统一频率:给所有页面都设"每 24 小时重爬",等于把 99% 的带宽浪费在静态页上
- ❌只看重要性不看变化率:高 PageRank 的档案馆页面可能一年不变,重爬它毫无收益
- ❌只看变化率不看重要性:一个频繁改动的垃圾页会挤占高价值页面的配额
- ❌忽略礼貌性:调度分数再高,也不该突破单 host 串行 + 延时的约束
- ✅正确姿势:S = P × (1 − F) 加权打分,总 QPS 预算做上限,front/back 两级队列分别管优先级与礼貌性
总结
爬虫爬取频率调度的完整答案就三句话:
- 公式:调度得分 S = 页面重要性 P × 新鲜度缺口 (1 − F),间隔 T 与 S 成反比
- 预算:用二幂法则估算 QPS 上限,重爬总预算固定,公式只负责分配
- 约束:front 队列管优先级、back 队列管礼貌性限流,内容哈希比对形成 freshness 反馈闭环
想深入更多组件细节(DNS 缓存、spider traps、数据验证等),可以直接阅读原书笔记 09. Web Crawler/Readme.md,整份 system-design-notes 仓库覆盖了从 Scaling 到分布式消息队列的 28 个系统设计主题,是新手理解大规模系统调度的优秀地图 🗺️
【免费下载链接】system-design-notesNotes of the book System Desgin Interview - An Insider's Guide项目地址: https://gitcode.com/GitHub_Trending/sy/system-design-notes
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考