聊抓取的时候,大家习惯盯抓取條數:今天来了多少次、覆盖了多少 URL。但很少人看每次抓取實际传了多少字节。對蜘蛛来说,時間是一份相對固定的预算,服務器响應、資料传輸、HTML 解析都要從這份预算里扣。頁面越重,同样一段時間里能走完的 URL 就越少。
一次抓取的耗时由几段组成
把一次抓取拆開看,大致是:建立连接、等待服務器返回首字节、下载响應体、解析 HTML 並提取連結。前三段和服務器、網絡有關,最後一段和頁面结构有關。很多站点只優化了首字节,却忽略了响應体本身。
举個粗略的對比:同样是一千個頁面,如果每個頁面的 HTML 從 200KB 压到 40KB,蜘蛛在传輸环节省下的時間相当可观。這不保證抓取量一定上升,但至少不會因為頁面太胖而把時間耗在下载上。
体积通常從哪里来
内联的脚本與样式
為了减少請求,不少站点把 CSS 和 JS 直接内联進 HTML。少量内联是合理的,但如果整站把框架代碼、图标字体、統計脚本全塞進每個頁面,HTML 會迅速膨胀。更极端的是把图片轉成 base64 内联,一張图就能顶掉几十 KB。
重复的模板区块
導航、頁脚、侧邊栏、推荐位,這些内容每個頁面都有。它們本身不算冗余,但如果再加上多层嵌套的容器、大量的 class 名和属性,模板部分的体积會明顯超過正文。
列表頁的卡片内容
列表頁往往塞進摘要、标簽、作者、時間、阅讀量、封面缩略图。這些對用戶有用,但對蜘蛛来说,真正需要的是指向詳情頁的連結。列表頁体积失控,最先受影响的就是分頁和翻頁連結的發現效率。
压缩與传輸
HTML 是文本,压缩收益很高。開啟 gzip 或 brotli 後,传輸体积通常能降到原来的两三成。检查一下服務器是不是對所有 text/html 响應都開了压缩,有些配置只压了 JS 和 CSS,HTML 反而漏掉了。
另外注意响應头里的 Content-Length 和實际传輸量是否一致,以及有没有在 HTML 里重复輸出大段 JSON 資料。前端渲染需要的初始資料,能精简就精简。
DOM 深度與出鏈位置
体积不只是字节數,還包括结构层級。DOM 嵌套過深时,解析成本上升,連結也容易被埋在中後段。一個實用的原則是:让重要的内鏈尽量出現在較浅的层級,不要為了样式包裹五六层 div 才放一個 a 标簽。
同样地,如果連結是通過脚本在頁面加载後動態插入的,蜘蛛即便拿到了 HTML,也未必能立刻看到這些出鏈。能用服務端直出的導航和列表,尽量直出。
抓取路径上的连鎖反應
頁面重,影响的不只是單個 URL。列表頁變慢,蜘蛛從這里發現新 URL 的速度就下降;詳情頁模板臃肿,每個被抓的頁面都多花一点時間。這些损耗叠加起来,表現在日誌里就是抓取频次没變、但覆盖的獨立 URL 變少。
体积優化不是一次性動作。模板改一次,所有頁面都會跟着變,值得放在和内容更新同等的位置去對待。
可以這样自查
- 抓几個典型頁面的原始 HTML,看未压缩大小,区分正文、模板、内联资源的占比。
- 確認服務器對 HTML 開啟了压缩,並對比压缩前後的传輸字节。
- 检查列表頁和詳情頁的 DOM 层級,找出嵌套最深的区块。
- 看服務器日誌里的响應時間和响應体大小,找出又大又慢的那批 URL。
- 把改動前後的抓取日誌做對比,观察獨立 URL 數量是否變化。
寫在最後
抓取優化里,体积是最不玄学的一环:改了什么,日誌里基本能看到。它不會直接带来排名,但會让蜘蛛在同样的時間里多走几頁。對小站来说,這可能就是多抓几十個 URL;對大站来说,是整体抓取效率的底數。