爬虫碰到“无限日历”“每次不同的会话 ID”“筛选条件的排列组合”这些页面,会把预算耗光在永远抓不完的 URL 上。这篇造一个有这些陷阱的本机站点,真实抓取,量一量各种常见防御到底有多管用、又会伤到什么。
BFS,最多抓 2000 个页面,各防御措施下找到多少个真实内容页、预算花在了哪类页面上 防御措施 抓到的真实页 覆盖率 浪费的请求(重复内容或无内容:日历/会话/筛选/循环) 无防御 262 / 263 100% 日历 370、会话 1074、筛选 288、循环 6、其它 0(共抓 2000) 只限制深度 ≤ 6 259 / 263 98% 日历 264、会话 348、筛选 288、循环 5、其它 0(共抓 1164) URL 长度 ≤ 80 262 / 263 100% 日历 370、会话 1074、筛选 288、循环 6、其它 0(共抓 2000) 检测路径段重复 ≥ 3 次 262 / 263 100% 日历 375、会话 1074、筛选 288、循环 1、其它 0(共抓 2000) 规范化时去掉 sid 参数 263 / 263 100% 日历 1424、会话 0、筛选 288、循环 25、其它 0(共抓 2000) 每个 URL 模板最多 50 个 103 / 263 39% 日历 101、会话 40、筛选 50、循环 1706、其它 0(共抓 2000) 去 sid + 路径重复 + 模板上限 50 113 / 263 43% 日历 101、会话 0、筛选 50、循环 1、其它 0(共抓 265) 去 sid + 路径重复 + 模板上限 300 263 / 263 100% 日历 601、会话 0、筛选 288、循环 1、其它 0(共抓 1153)
陷阱:日历(上下月、每月 28 个日期页,无限)、会话页(同样 20 个页面但链接里 sid 每次不同)、筛选列表(288 种参数组合)、相对链接循环。无防御时 BFS 靠“真实页在前”的运气找到几乎全部真实页,但 2000 个请求里 1738 个是浪费。只限深度 ≤ 6 能让队列空掉(1164 个请求,98% 覆盖);去掉 sid 参数让会话浪费归零,却让预算转移到日历上(1424);URL 长度和路径重复检测对这个站点作用很小。
无防御:抓 6000 个页面,找到真实页 263 / 263;队列里还剩 10094 个待抓 去 sid + 路径重复 + 模板上限 50:抓 265 个页面,找到真实页 113 / 263;队列里还剩 0 个待抓 去 sid + 路径重复 + 模板上限 300:抓 1153 个页面,找到真实页 263 / 263;队列里还剩 0 个待抓
按模板限制数量是最通用的办法,但上限定得太低会误伤正常的大站点:上限 50 时,200 篇文章只抓了 50 篇,真实页覆盖只剩 39%。上限 300 配合去 sid 与路径重复检测,263 / 263 全部找到,抓了 1153 个后队列清空,日历仍浪费了 601 个。更好的办法需要内容层面的信号(重复内容、页面是否有新的出链),本文没有实现。