蜘蛛對 JavaScript 的處理不是统一的
不同搜尋引擎的蜘蛛對 JS 的执行能力差別很大。有的蜘蛛只抓取初始 HTML,不执行脚本;有的虽然能渲染,但會排入單獨的渲染队列,時間上滞後很多。這就意味着,如果你的入口頁把關键連結和内容都交给 JS 生成,蜘蛛可能只看到一個空框架。
所以讨论入口頁的 JS 渲染,核心問题不是“能不能用 JS”,而是“哪些信息必须让蜘蛛在第一次抓取时就拿到”。
蜘蛛渲染和普通抓取不是一回事
即使蜘蛛具备渲染能力,很多搜尋引擎也會把渲染放在獨立的队列里。初始抓取和渲染之間可能間隔一段時間,入口頁數量一多,這個延迟會被放大。如果你的入口頁主要作用是传递連結權重和引導 URL 發現,等待渲染队列顯然不划算。
另外,渲染會消耗更多资源。搜尋引擎不會對每個頁面都投入同样的渲染预算,入口頁越薄、越模板化,被跳過渲染的概率越高。
這些内容建议放在初始 HTML 里
- 可抓取的連結:指向目标頁的 a 标簽最好直接出現在 HTML 中,而不是等 JS 插入。蜘蛛顺着連結發現新 URL,依赖的就是這些初始的 href。
- 頁面主题相關的主标题和正文摘要:至少让蜘蛛讀到入口頁在讲什么,有助于判断是否繼續抓取。
- canonical 和 meta robots:這些声明如果由 JS 後置寫入,蜘蛛可能来不及看到,規范化和屏蔽指令就會失效。
- 狀態碼和跳轉:服務端能返回的,不要改用前端路由或 JS 跳轉代替。HTTP 层面的信号更明确。
预渲染與動態渲染的取舍
如果入口頁确實需要 JS 才能展示完整内容,可以考虑预渲染或動態渲染,但要注意成本和一致性。
预渲染
在构建或缓存阶段就把頁面渲染成静態 HTML,蜘蛛和用戶拿到的是同一份内容。這種方式稳定,但内容更新後需要重新生成,适合入口頁结构相對固定的场景。
動態渲染
根據 User-Agent 判断是否返回渲染後的 HTML。實現时要小心:蜘蛛 UA 會變化,伪装 UA 的爬虫也不少。如果只對特定 UA 返回不同内容,容易造成内容不一致,也可能被判定為作弊。更稳妥的做法是服務端渲染或同构渲染,让所有訪問者拿到基本一致的 HTML。
几個容易踩的坑
- 把連結做成 onclick 事件,或者用 javascript:void(0) 這類空地址,蜘蛛拿不到真實目标。
- 首屏内容由接口异步加载,初始 HTML 里只有 loading 提示。
- 用前端路由處理分頁,URL 變了但 HTML 不變,蜘蛛容易把不同頁看成同一頁。
- 依赖 JS 寫入 meta 标簽,比如 noindex 或 canonical,實际抓取时可能根本没生效。
怎么確認蜘蛛看到了什么
最直接的办法是看服務端日誌里的請求。如果蜘蛛只請求了 HTML,没有請求 JS 和接口,那它大概率没有执行渲染,或者渲染在另一個阶段進行。也可以對比“源代碼”和“渲染後 DOM”的差异,差异越大,風險越高。
如果日誌顯示蜘蛛抓取了 JS 文件,但入口頁的連結仍然没有出現在後續抓取中,需要检查連結是否在初始 HTML 里,以及是否被 JS 條件隐藏。
一個简單的检查顺序
- 查看頁面源代碼,而不是開發者工具里的渲染後 DOM。源代碼里有没有連結、标题和正文?
- 禁用浏览器 JavaScript,看頁面還剩多少可讀内容。
- 用抓取工具模拟蜘蛛,只拿初始 HTML,確認關键元素是否出現。
- 检查 canonical、meta robots 和主要連結是否都在服務端輸出。
- 如果必须用 JS,评估预渲染或 SSR 的成本,別只靠動態渲染兜底。
入口頁的 JS 策略,本质上是在“開發方便”和“蜘蛛可讀”之間做取舍。能服務端輸出的,尽量別留给客戶端。