蜘蛛顺着連結走,連結在哪儿,抓取路径就延伸到哪儿。但很多站点把入口藏在了「点击之後」——按钮、下拉菜單、JavaScript 路由。對抓取来说,這些位置等于没有連結。下面梳理這類入口的形態、排查方法和改造顺序。
哪些入口属于「点击才出現」
- 「加载更多」按钮:首屏只渲染十條,剩余條目靠点击後請求接口再插入頁面。
- JS 路由:菜單項绑定的是脚本跳轉,地址栏變化由前端完成,初始 HTML 里没有對應地址。
- 下拉菜單與折叠面板:子分類地址在悬停或展開後才進入 DOM。
- Tab 切換:只渲染目前标簽的内容,其余分類的連結在初始頁面里根本不存在。
- 整块卡片点击跳轉:绑定了点击事件,但没有可识別、可複製的地址。
抓取程序看到的是什么
抓取程序拿到的是服務器返回的 HTML,或者渲染之後的 DOM。前者不含脚本生成的連結,後者取决于渲染是否成功、异步請求是否跑完。常见的寫法里,「可点击」和「可抓取」是两件事:button 元素没有 href,href 填一段脚本代碼不是有效地址,data-href 只是自定义属性,寫在点击事件里的跳轉逻辑對連結解析没有意义。
结果就是:頁面在人眼里完整,在抓取路径里却是一堵墙。列表翻到第二頁之後、折叠起来的子分類、Tab 里的商品列表,全都停在墙外,只能靠別處的連結偶然被带到。
怎么確認自己踩了這個坑
- 關閉 JavaScript 加载頁面,或直接查看渲染前的源碼,看看導航和分頁還剩多少可点連結。
- 對照抓取日誌:某個栏目如果只有首頁有记錄,第二頁往後完全没有訪問痕迹,多半是入口問题,而不是内容問题。
- 統計頁面數量與指向深层頁面的連結數量,两者差距悬殊时值得警觉。
- 随便挑一個深层地址,問自己:從首頁出發,纯靠普通連結几步能到?如果答案是「到不了」,問题就確認了。
改造顺序
- 主入口改成真實連結。導航、分頁、分類、上一頁下一頁,都用带 href 的連結,脚本只做增强,不做唯一通道。
- 分頁保留可獨立訪問的地址。点击「加载更多」之後,列表也應该對應一個能直接打開的相對地址,比如带 page 參數或 /page/2/ 的形式。
- 折叠和 Tab 内容尽量预渲染。至少让子分類和代表性連結出現在初始 HTML 中,再用样式隐藏。
- 服務端渲染或预渲染關键頁面。渲染失敗时要有可讀的降級内容,而不是一個空容器。
- 用 Sitemap 兜底,但別当替代品。Sitemap 能說明有哪些地址存在,内鏈才决定抓取的先後與路径走向。
几個容易忽略的细节
一是「下一頁」只在滚動到底部时才出現,抓取程序到不了那個位置;二是無限滚動没有终点,也没有可枚举的地址;三是篩選條件靠脚本拼接,用戶看得到、抓取程序拿不到;四是顺手给分頁連結加了 nofollow,等于自己把路封上。
連結的價值不在于样式上能不能点,而在于 HTML 里是否存在一個明确的地址。把入口寫成地址,是 URL 發現中最省事的一步。
如果不打算大改前端,可以先把最重要的三五個入口——主導航、栏目分頁、詳情頁推荐位——改成真實連結,再逐步處理 Tab 與折叠区域。改動之後观察抓取日誌里深层地址的出現情况,比反复猜测更有效。