分布式爬虫系统设计
一、核心需求
| 需求 | 说明 |
|---|---|
| 大规模抓取 | 每天抓取数十亿网页 |
| 礼貌性抓取 | 遵守 robots.txt,不压垮目标站点 |
| 去重 | 同一个 URL 只抓一次 |
| 优先级调度 | 重要页面优先抓取 |
| 容错 | 爬虫节点宕机不影响整体进度 |
二、系统架构
1 | ┌──────────────────────────────────────────┐ |
三、URL Frontier
3.1 设计要点
URL Frontier 是分布式爬虫的大脑,负责管理待爬取 URL 的调度和分发。核心功能:
去重:
使用布隆过滤器检测 URL 是否已爬取。百亿级 URL,0.01% 误判率 → 约 24GB 内存。为了支持长期运行,定期(如每周)从持久化存储重建布隆过滤器。
礼貌性控制:
同一域名的两次请求间隔 ≥ politeness_delay(通常 1-10 秒)。策略是按域名分配后端队列,爬虫节点从各域名队列中轮流取 URL:
1 | 域名队列: |
优先级:
| 优先级 | URL 特征 | 示例 |
|---|---|---|
| 高 | 首页、热门页面、频繁更新的页面 | 新闻首页 |
| 中 | 文章页、产品页 | 博客文章、商品详情 |
| 低 | 用户评论页、历史归档 | 2010 年的归档新闻 |
3.2 分布式实现
按域名分片避免多个爬虫同时爬同一域名:
1 | URL Frontier 分片策略: |
四、爬虫节点设计
4.1 抓取流程
1 | 1. 从 URL Frontier 获取一个 URL |
4.2 HTML 解析
HTML 解析的目的是:
- 提取链接:所有
<a href="...">标签,处理相对路径 - 提取内容:标题、正文、发布时间(用于搜索引擎索引)
- 规范化 URL:移除 fragment、排序 query 参数、去重协议(http vs https)
4.3 robots.txt 处理
每个域名在首次抓取时需要下载并解析 robots.txt:
1 | User-agent: * |
将此解析为规则集并缓存。每个爬虫节点在抓取 URL 前先检查是否被允许,减少对目标站点的压力。
五、去重策略
5.1 为什么去重如此重要
互联网上的页面存在大量重复链接:同一个页面被多个页面引用、URL 参数变化导致表面不同的 URL、HTTP/HTTPS 双版本等。不去重会导致:
- 浪费带宽重复抓取同一内容
- 目标站点压力剧增
- 存储大量重复数据
5.2 布隆过滤器方案
1 | 布隆过滤器配置: |
优化方案:按域名分片的布隆过滤器
1 | 每个域名的布隆过滤器只需要覆盖该域名下的 URL 数量: |
5.3 URL 规范化
在进入布隆过滤器之前,需要对 URL 做规范化(Canonicalization):
1 | 原始 URL: http://www.example.com:80/path?b=2&a=1#section |
六、内容提取与存储
6.1 内容去重
即使 URL 不同,页面内容也可能完全相同(镜像站、CDN 等)。除了 URL 去重,还需要内容去重。使用 SimHash 或 MD5 签名来实现:
1 | 对于每个抓取的页面: |
SimHash 的额外优势:两个页面即使内容不完全一致,如果 SimHash 的汉明距离很小(< 3),说明它们高度相似,可能是镜像站或转载,可以选择只保留一个版本。
6.2 存储
| 数据 | 存储 | 说明 |
|---|---|---|
| 原始 HTML | 对象存储 (S3/HDFS) | 压缩后存储 |
| 结构化数据 | 宽表 (HBase/Cassandra) | URL、标题、时间、关键词 |
| 链接图 | 图数据库或 K-V 存储 | URL → {引用该 URL 的页面列表} |
| 爬虫状态 | Redis | 当前进度、速率、错误率 |
七、爬虫陷阱与反爬对抗
7.1 常见陷阱
| 陷阱类型 | 表现 | 应对 |
|---|---|---|
| 无穷日历页 | 某个博客按日期归档,日期链接无穷无尽 | 限制路径深度、限制同域名下的链接数量 |
| Session ID 陷阱 | 每次访问生成新的 session ID 参数导致 URL 无限增多 | URL 规范化时去掉 session 参数 |
| 动态页面 | 页面内容根据参数不断变化(搜索页、过滤页) | 识别低价值页面类型,降低优先级或直接跳过 |
| 重定向循环 | A → B → C → A | 限制重定向次数(≤ 5 次),记录重定向链 |
7.2 反爬对抗
现代网站大量使用反爬技术,企业级爬虫需要相应策略:
- IP 代理池:维护数千个代理 IP,每个域名分配不同的出口 IP
- User-Agent 轮换:模拟不同浏览器和设备的 User-Agent
- 渲染引擎:对于 SPA (React/Vue) 页面,使用 Headless Chrome 渲染后再提取内容
- 行为模拟:鼠标移动、滚动等,降低被检测为爬虫的概率
八、容量估算
假设目标:每天抓取 10 亿网页
- 平均页面大小 100KB → 每天下载 10亿 × 100KB = 100TB
- 平均抓取速度 50 页/秒/节点 → 需要 10亿 / (50 × 86400) ≈ 230 个爬虫节点
- 考虑网络延迟和处理开销,实际需要 300-500 个节点
九、小结
分布式爬虫的核心挑战是规模和礼貌性的统一。URL Frontier 的优先级调度和域名分片策略保证了公平高效的抓取,布隆过滤器提供了 O(1) 的去重能力,URL 规范化和 SimHash 去重则进一步减少了存储浪费。Google、CommonCrawl 等大型搜索引擎都在此架构基础上做了各自的优化——比如 Google 使用自研的 Caffeine 索引系统处理实时更新,CommonCrawl 每两个月抓取一次全量快照作为公开数据集。