讨论抓取时,多数人盯着“蜘蛛有没有发现这个 URL”。但发现只是第一步,蜘蛛还要把页面读完、抽出链接、判断内容,然后才决定下一次来不来。页面本身有多重、解析起来有多费劲,会直接影响一台爬虫在一段时间里能走完多少页面。
抓取预算的两笔账:请求数和字节数
搜索引擎分配给站点的抓取资源,大致可以从两个维度看:单位时间内发起的请求数,以及愿意为每个请求读取的响应字节。请求数决定蜘蛛能覆盖多少 URL,字节数决定它一次能读多深。两者会互相挤占:如果一个页面的响应体特别大,蜘蛛在这个 URL 上停留的时间变长,同样的抓取窗口里能处理的 URL 就变少。
对小站来说这通常不是问题;但当站点有成千上万个 URL,且其中一部分页面异常臃肿时,抓取队列的推进速度会明显被拖住。
HTML 体积从哪里膨胀
同一个页面,内容差不多,输出体积可能差好几倍。常见的几个来源:
- 内联资源:把大量 CSS、JavaScript 甚至 base64 编码的图片直接写进 HTML,每次响应都要重复传输一遍。
- 模板残留:注释掉的模块、隐藏的 DOM、重复输出的结构化数据,用户看不到,蜘蛛照单全收。
- 列表渲染:列表页一次输出几百条记录,每条又带完整的卡片结构。
- 未压缩的响应:服务端没有开启 gzip 或 brotli,文本类 HTML 白白多传好几倍。
DOM 深度与节点数量
体积之外,结构本身的复杂度也有成本。蜘蛛需要解析 HTML、构建节点树,再从里面提取链接。层次很深、节点极多的文档,解析耗时更长,链接也更容易被埋在大段样板里。
常见的坏味道包括:为了布局而写下的多层无意义嵌套、在每个列表项里重复完整导航、把正文拆成大量细碎的行内标签。这些都不会让页面变得更好理解。
链接密度比链接数量更重要
页面里链接多不等于对蜘蛛友好。如果一页有几百个链接,但绝大多数指向同一批 URL(导航、页脚、推荐位),有效入口就被稀释了。真正有帮助的是让不同区域的链接指向不同目标,并且把重要入口放在文档靠前、结构更浅的位置。
渲染抓取会额外放大成本
如果页面依赖 JavaScript 才能呈现内容,蜘蛛除了取回 HTML,还要排队执行脚本、等待接口返回。这一步的成本远高于静态解析:脚本执行有时间上限,接口慢或超时,蜘蛛可能只看到空壳。
对内容页而言,把正文和主要内链放在服务端直出的 HTML 里,能同时降低抓取成本和不稳定性。
怎么自查
不需要复杂工具,服务器日志里就能看出线索:
- 看蜘蛛请求的响应字节数分布,找出明显偏大的那批 URL。
- 看单次请求的处理时间,区分是服务端慢还是页面大。
- 看状态码,2xx 才是有效读取;5xx、429 会打断队列。
- 抽样把页面 HTML 存下来,看体积和节点结构是否符合预期。
- 对比列表页与详情页的抓取频率,判断哪一类更拖后腿。
可以做的事
- 开启传输压缩,减少 HTML 的实际传输量。
- 把内联的大段脚本、样式外链,并做缓存。
- 控制单页链接总量,优先保留指向不同 URL 的入口。
- 列表页分页输出,避免一页塞进上千条记录。
- 内容与核心内链服务端直出,脚本负责增强而非承载。
不要为了“让蜘蛛轻松”而删掉对用户有用的内容。先解决浪费:重复传输、隐藏模块、无意义嵌套。抓取效率的改善,通常来自这些看得见的冗余,而不是内容的削减。
抓取是一个持续的过程,蜘蛛每次来访都在做取舍:读这个页面值不值。降低单页成本,等于把同样的抓取窗口让给更多 URL,尤其是那些还需要被发现的页面。