搜尋抓取

响應体积、压缩與 304:蜘蛛每次抓取的下载成本

抓取不只看次數,也要看每次下载了多少字节。本文從 HTML 内联资源、gzip/brotli 压缩、Last-Modified 與 ETag 触發的 304,以及 JS 渲染的額外下载等角度,說明如何降低蜘蛛單次抓取的传輸成本,並给出可执行的测量方法。

搜尋抓取

响應体积、压缩與 304:蜘蛛每次抓取的下载成本

很多站点谈抓取时,注意力都在“蜘蛛有没有来”“来了多少次”,却很少算另一筆帳:每来一次,蜘蛛要下载多少字节。抓取本身是有带宽和時間成本的,同样一段時間里,响應越轻,能走完的 URL 越多;响應越重,能覆盖的頁面就越少。

一次抓取的下载成本由什么构成

一次抓取大致包含三部分:請求头、响應头、响應体。前两者通常只有几百字节,真正的大头是响應体。响應体既包括 HTML 本身,也包括服務端直接内联進去的内容,這部分最容易被忽略。

HTML 体积常见的几個膨胀点

内联的 base64 图片與字体

把图片轉成 base64 直接寫進 HTML 或 CSS,頁面看起来“少了一個請求”,代價是体积增加约三分之一,而且這段内容無法被浏览器單獨缓存,每次抓取都要重下。

直接塞進頁面的資料

一些框架會把整份狀態資料内联進 HTML,再由前端渲染。用戶只看到頁面的一部分,蜘蛛下载的却是全部資料。当資料量随列表長度线性增長时,抓取成本也跟着涨。

冗余结构與注释

深层嵌套的 DOM、重复的样式声明、大段調试注释,都會進入响應体。單獨看都不大,叠加在模板里就很可观。

压缩:性價比最高的一步

HTML、CSS、JS、JSON 都是文本,压缩率通常很高。開啟 gzip 或 brotli 後,几百 KB 的 HTML 常常能压到几十 KB。這通常是成本最低、最好驗證的一步。

  • 確認服務器确實返回了 Content-Encoding: gzip 或 br,而不只是配置里寫了開啟。
  • 不要把已经压缩過的格式(图片、视频、woff2、zip)再压一遍,收益极小,還多耗 CPU。
  • 如果经過 CDN,要分清压缩在源站還是邊缘节点完成,避免“源站压了、CDN 又压一次”,或者两头都没压。
  • 压缩會增加服務器 CPU 開销,抓取高峰时可以配合缓存,把压缩结果缓存下来,而不是每次現压。

减少重复下载:Last-Modified、ETag 與 304

蜘蛛再次訪問同一個 URL 时,通常會带上 If-Modified-Since 或 If-None-Match。如果頁面没變,服務器返回 304,响應体為空,這次抓取几乎不消耗传輸成本。要让它真正生效,有几個前提:

  • 這两個头要稳定:同一份内容不要每次請求都生成一個新的 ETag。
  • 頁面有實质更新时要让 Last-Modified 随之變化,否則蜘蛛會一直拿到 304,看不到新内容。
  • 304 省掉的是响應体,請求本身仍然會發生,所以它不能替代對 URL 數量本身的控制。

渲染型頁面的額外成本

如果頁面靠 JS 渲染,蜘蛛除了下载 HTML,還要下载並执行 JS、CSS。這时体积的影响不止在文档本身:一個体积庞大的脚本包,會同时抬高下载、解析和执行的時間。把首屏不需要的脚本延迟加载、适当拆分打包,對抓取的稳定性會有帮助。

怎么量一遍

  1. 用命令行看压缩前後的大小差异:curl -H "Accept-Encoding: gzip" -s -o /dev/null -w "%{size_download}" URL,再對比不带压缩头的结果。
  2. 在浏览器開發者工具里查看文档請求的“传輸大小”和“资源大小”,两者的差距就是压缩带来的收益。
  3. 在頁面源碼中搜尋 base64, 與内联 JSON,估算它們占了多少字节。
  4. 如果能看到抓取日誌,留意下载字节數,找出明顯偏大的頁面,這類問题通常集中在列表頁和詳情頁模板。

有些体积不必省

压缩和内联都需要權衡:把正文拆成异步加载、只让用戶看到,對抓取没有好處;為了减小 HTML 把關键内容全部改成前端拼接,也可能让内容抓不到。目标不是把頁面做到最小,而是在内容完整的前提下,把不必要的传輸去掉。

在抓取優化里,减少“每次抓取要传的東西”和增加“被抓的入口”同样重要,前者往往更容易测量和驗證。

可以挑一两個模板頁面先做測試:看压缩前後的大小、看 304 的命中情况,再决定改哪里,比全站铺開容易收场。