把連結交给 JavaScript 輸出,在蜘蛛池入口頁里非常普遍:模板统一、改起来方便,還能顺手加統計和條件判断。問题在于,搜尋蜘蛛拿到的第一份 HTML 里往往並没有那些連結,發現目标 URL 的路径就多了一道工序。
搜尋蜘蛛不是在第一步就看到 JS 结果
搜尋蜘蛛抓取一個頁面,通常先拿到服務器返回的原始 HTML。如果連結是 JS 执行後才寫進 DOM 的,原始 HTML 里就是空的。搜尋引擎随後可能把頁面放進渲染队列,用浏览器内核执行 JS,再取一次渲染後的内容。但這個环节有時間差,也不是每個頁面都會被渲染。
也就是说,JS 渲染的連結並非完全抓不到,而是從“抓取即發現”變成了“渲染後才發現”,中間多了排队、失敗、超时几種可能。
哪些寫法最容易让連結丢失
- 用 document.write 或字符串拼接生成的 a 标簽:渲染时序不稳定,容易被截断。
- 依赖接口返回資料再插入連結:接口慢、跨域或需要登入时,渲染阶段拿不到資料。
- 点击或滚動才加载:折叠区域、懒加载列表,搜尋蜘蛛通常不會主動去点、去滚。
- 只在事件回調里輸出的連結:頁面初始渲染时根本不存在。
- 用 hash 路由拼出的地址:渲染後可能仍是 #/xxx 形式,不是一個可抓取的目标 URL。
還要区分“連結存在”和“連結可执行”。有些寫法把地址放在 JS 變量里,再统一绑定点击事件,视觉上像連結,但 DOM 里没有 href,搜尋蜘蛛無法顺着走。
自查入口頁的四步
- 用浏览器的“查看網頁源代碼”(不是审查元素)打開入口頁,搜尋目标 URL 的域名,看它是否出現。
- 在關閉 JS 的情况下打開同一頁面,观察頁面里還剩多少可点击的連結。
- 查看渲染後的 DOM,確認 a 标簽带 href,且地址是完整的 http 或 https 連結。
- 對照服務器訪問日誌或渲染日誌,確認搜尋蜘蛛有没有對這個頁面發起過渲染請求。
如果第一步就搜不到域名,而目标 URL 又只靠 JS 輸出,那這個入口頁在“發現”這件事上基本是空轉的。
更稳妥的做法:静態兜底,JS 做增强
比較常见的處理方式,是让連結在原始 HTML 里就存在,JS 只负责增强体驗:
- 服務端渲染或模板直接輸出 a 标簽,把目标 URL 寫在 href 里。
- 需要异步資料时,先渲染一份静態連結列表,JS 加载完成後再替換。
- 分頁、篩選這類交互,给每個狀態准备一個可直達的静態地址。
- 頁面底部或侧栏保留一组稳定的文字連結,作為兜底入口。
判断标准很简單:把 JS 全部關掉後,入口頁里還能不能找到通向目标 URL 的可点击連結。能,就是稳的;不能,就要考虑加一层静態輸出。
和其他發現渠道配合
JS 渲染不是唯一變量。入口頁如果同时存在响應慢、狀態碼異常、robots 規則冲突等問题,渲染环节更容易失敗。比較務實的做法是:入口頁保持静態可讀,sitemap 里同步列出入口頁地址,再观察日誌中搜尋蜘蛛對入口頁和目标 URL 的抓取记錄,判断問题到底出在“没發現”,還是“發現了但没抓”。
需要提醒的是,這些都只是提高被發現的确定性,並不代表目标 URL 一定會被收錄或获得排名。真正可控的部分,是把入口頁做得简單、明确、可解析,让搜尋蜘蛛少走弯路。