不少站点的導航、列表和“相關阅讀”是前端框架渲染出来的:HTML 源碼里只有一段脚本,連結是頁面加载之後才被塞進 DOM。對人来说看不出区別,但對搜尋蜘蛛来说,抓取路径可能就断在這里。這篇聊三件事:蜘蛛打開頁面时先看到什么、哪些連結寫法更容易被顺着走、發現不了时怎么兜底。
蜘蛛進頁面时,先拿到的是原始 HTML
蜘蛛請求一個 URL,服務器返回的响應体就是它第一眼看到的内容。如果連結只存在于 JS 执行後的 DOM 里,蜘蛛要么需要排队做渲染,要么這一次抓取就拿不到這些連結。渲染本身有成本,站点越大、需要渲染的頁面越多,能排到的机會就越不确定。所以問题不是“渲染能不能拿到連結”,而是不要把全部的 URL 發現都押在渲染上。
哪些連結寫法通常更稳
- 标准的 a 标簽加 href:href 指向真實 URL,而不是 href="#" 或 javascript:void(0)。
- 服務端渲染或静態生成的頁面:連結直接出現在返回的 HTML 里。
- 同域内鏈:跨域連結對本站 URL 發現帮助有限。
- 能被右键複製出完整地址的連結,一般是真連結。
几種常见的 JS 寫法,结果不太一样
用框架的路由组件渲染連結
如果是纯客戶端渲染,HTML 里往往只有一個挂载点。蜘蛛要拿到連結,得等渲染队列。首屏的關键導航最好放在服務端輸出的 HTML 中,別全交给脚本。
点击後才插入 DOM 的連結
“加载更多”、折叠菜單、轮播這類連結預設藏在交互後面。蜘蛛一般不會去点按钮,除非它把頁面完整跑一遍脚本再抓。比較稳妥的做法是:想让蜘蛛走的 URL 直接寫在 HTML 里,用 CSS 控制顯示與隐藏,而不是用 JS 控制它是否存在。
pushState 或脚本跳轉
這類寫法只产生行為,不产生連結。用戶点一下會跳走,但蜘蛛看不到“這條路”,因此它不會成為新的 URL 入口。
让重要 URL 更早、更稳定地被看到
- 把主干的連結寫進 HTML:首頁、栏目頁、正文頁之間的關键導航。
- 正文内鏈用 a 标簽,直接指向最终 URL,少绕几层脚本跳轉。
- 列表翻頁、篩選结果如果确實希望被抓,就用可爬的連結形式;如果不希望被抓,用 robots.txt 或頁面級指令收口,而不是靠 JS 藏起来。
- 用 Sitemap 做兜底,把服務端能輸出的 URL 集中列一份,作為發現通道之一。
- 別让重要 URL 只出現在 Sitemap 里,也別只出現在 JS 里,两條通路都留着更稳。
怎么核對蜘蛛到底看没看到
與其猜,不如看记錄。抓取日誌里能看到蜘蛛請求了哪些 URL;如果日誌里長期只有首頁和少數几個入口,正文頁從没被請求過,那連結很可能没有被解析到。也可以把頁面的原始 HTML(不执行脚本时的响應体)拉出来看一眼:里面有没有指向内頁的 a 标簽,其實很好判断。核對日誌时注意区分真實蜘蛛和模拟請求,別把第三方工具的记錄当成官方抓取。
渲染不是免費的。每一次需要执行 JS 的抓取,都要占用蜘蛛的時間和站点资源。什么时候被抓到,取决于站点整体情况,没有谁能保證结果。
小结
JS 渲染本身不是問题,問题是把 URL 的發現完全交给 JS。把主干連結落到 HTML 里,把可選項留给渲染,再用 Sitemap 和日誌各核對一遍,抓取路径會清楚很多。