搜尋抓取

懒加载與無限滚動:蜘蛛不滚動頁面,内容怎么被找到

懒加载和無限滚動让頁面在浏览器里更轻,但蜘蛛不會滚動,也不會点“加载更多”。本文說明内容在哪些寫法下會被漏掉,以及怎样用真實連結、静態分頁、聚合頁和 Sitemap 给深层内容补一條可抓取的路径。

搜尋抓取

懒加载與無限滚動:蜘蛛不滚動頁面,内容怎么被找到

懒加载和無限滚動本来是為了让頁面更快、更省流量:先加载首屏,剩下的等用戶往下滚再取。問题是,搜尋蜘蛛不滚動頁面,也不点击按钮。它拿到的往往只是首屏那一份 HTML,後面被“省下来”的内容,如果没有別的入口,就很难進入抓取队列。

蜘蛛看到的是初始响應,不是滚動後的頁面

蜘蛛請求一個地址时,拿到的是服務器返回的 HTML,以及它能执行的脚本渲染结果。滚動、点击、悬停這類交互行為不在它的動作清單里。所以判断一個頁面能不能被完整抓到,關键不是用戶能不能看到,而是不滚動、不点击时,内容和連結在不在。凡是必须靠交互才會出現的連結,都要預設它處于不可抓取的狀態。

懒加载的两種寫法,结果差別很大

原生懒加载属性

img 标簽上的 lazy 属性只是推迟加载时机,地址本身仍在 HTML 里,蜘蛛讀源碼时能看到 src 或 srcset。這類寫法對抓取基本没有影响,最多是图片资源本身稍晚被取走。

把地址放在脚本里,滚動时再插入

另一種寫法是先用占位符,等滚動到视口附近,再用脚本把真實地址寫進 img 或容器。如果頁面没有预渲染,蜘蛛在脚本执行完之前讀到的就是空占位符。文字内容被這样注入时風險更大:它可能既不進正文,也不产生連結。

無限滚動:地址不變,内容却在換

無限滚動通常不會為新出現的内容生成新 URL,或者只在浏览器地址栏里用脚本改一下。對蜘蛛来说,一個地址對應一份内容,它不會“往下滚”去看後面的條目。

  • 所有内容挤在同一個 URL 里,後面的條目很难被單獨發現和评估;
  • 用脚本拼出的分頁地址,如果没有静態連結指向,等于不存在;
  • 即使用 History API 改了地址,直接訪問该地址能否返回同样内容,也要單獨驗證。

“加载更多”尽量做成真實連結

按钮最容易踩的坑是寫成 button 加 onclick。视觉上没問题,但對蜘蛛来说頁面里根本没有可跟随的地址。更稳妥的做法是把它做成一個普通的 a 标簽,href 指向下一頁的真實地址,再用脚本拦截点击、改成局部加载。

顺序很重要:先保證 HTML 里有可抓取的連結,再考虑用脚本優化体驗。反過来做,蜘蛛看到的就是一個没有出口的頁面。

给深层内容补一條可抓取的路径

交互体驗不必改,但需要另外铺设几條给蜘蛛走的路径:

  1. 在列表頁提供常規分頁連結,指向 /list/2、/list/3 這類静態可達的地址;
  2. 把深层條目按栏目或時間归档,生成一批可遍歷的聚合頁;
  3. 在 Sitemap 里列出這些分頁與聚合地址,並保證每個地址直接訪問都有稳定内容;
  4. 重要條目在相關正文里用内鏈指向,形成不依赖脚本的路径。

這几種方式不冲突,可以同时存在。差別只在于谁先被蜘蛛發現,以及服務器要為抓取多承担多少請求。

自查:把脚本關掉,再看一遍頁面

最直接的办法是禁用 JS 打開頁面,看是否還能讀到主要内容和連結,或者用抓取工具對比源碼與渲染後的结果。另外可以翻一翻服務器日誌:如果某個分頁或聚合頁很久没有蜘蛛訪問记錄,多半說明它在 HTML 里缺少入口,而不一定是内容本身的問题。

懒加载本身不是問题,把内容的可達性完全交给用戶交互才是問题。让每一层内容至少有一條不需要点击就能走到的地址,抓取路径才不容易断在首屏。