入口頁上放目标連結,是蜘蛛池里最常见的操作之一。現在不少入口頁是用前端框架或者一段脚本拼出来的,連結在浏览器里看得见,但服務器返回的原始 HTML 里找不到。這種情况下,搜尋蜘蛛能不能發現目标 URL,答案不是简單的能或不能,而是取决于連結出現在哪個环节。
先確認一件事:連結在不在初始 HTML 里
用浏览器打開入口頁,右键查看網頁源代碼(注意不是“检查元素”)。如果在源代碼里搜不到目标 URL,那這條連結就属于需要执行 JavaScript 才會出現的類型。搜尋引擎處理這類連結的方式,和普通 HTML 連結並不一样。
搜尋蜘蛛處理 JavaScript 的基本流程
主流搜尋引擎通常分两步走:先抓取服務器返回的 HTML,把頁面放進渲染队列;之後再安排一次带渲染能力的抓取,执行頁面上的脚本,拿到渲染後的 DOM,再從里面提取連結。
也就是说,JS 渲染出来的連結是有机會被發現的,但要穿過更多环节:渲染队列可能积压、脚本可能报错、外部资源可能加载失敗或超时、渲染结果可能不完整。任何一個环节出問题,這條連結在那一轮抓取里就不會被發現。
容易被漏掉的几種寫法
- 用 innerHTML 拼接字符串插入連結,或者在脚本里用 document.write 輸出連結
- 連結要等某個接口返回資料之後才插入,接口慢或失敗时頁面上什么都没有
- 需要用戶点击“展開更多”“加载更多”才會出現
- 用 onclick 加 location.href 跳轉,而不是标准的 a 标簽加 href 属性
- 設定了較長的延时(比如几秒後才插入),渲染抓取的等待窗口可能等不到
- 内容依赖登入狀態、cookie 或者特定地区判断,抓取时拿不到同样结果
想让目标 URL 更容易被發現,可以這样做
- 把最關键的目标連結放在服務端渲染的 HTML 里,脚本只负责附加内容
- 用标准 a 标簽加 href,不要用按钮或 div 模拟連結
- 如果确實要异步插入,尽量缩短等待時間,不要依赖用戶交互触發
- 保證接口和静態资源可正常訪問,別让渲染過程因為某個资源返回 4xx、5xx 而中断
- 在入口頁保留一份纯 HTML 的兜底連結列表,脚本加载失敗时仍有連結可抓
怎么驗證連結有没有被渲染到
- 關閉浏览器 JavaScript 再看頁面,如果連結全部消失,說明嚴重依赖渲染
- 看服務器日誌里有没有带渲染特征的抓取請求,以及脚本、接口等渲染资源是否被請求過
- 對比原始 HTML 抓取和渲染抓取的時間,看渲染抓取是不是经常缺失或失敗
- 检查渲染相關請求有没有大量 429、超时,這通常意味着抓取预算被浪費掉了
JS 渲染只代表“有机會被發現”,不代表一定被發現,更不代表會被收錄或获得排名。入口頁本身的可訪問性、稳定性和内容质量,仍然是更基础的前提。
常见的几個誤区
- 以為“浏览器能看到,搜尋蜘蛛就能看到”,但浏览器和爬虫的执行环境並不等價
- 以為渲染抓取是無限次的,實际上渲染消耗资源,频率和配額都有限
- 以為單頁應用不需要任何處理,如果路由用 history API 又没有服務端兜底,連結往往更难被發現
- 把所有連結都交给脚本生成,原始 HTML 里空無一物,抓取预算花在渲染上却没換来 URL 發現
小结
如果入口頁的目标連結必须由 JavaScript 才能出現,處理思路其實很直接:能放回 HTML 的就放回 HTML;放不回去的,缩短渲染依赖鏈、减少外部资源阻塞、保留兜底連結,然後用日誌確認渲染抓取到底有没有發生。發現只是第一步,之後的抓取和收錄,還要看目标頁面自身的情况。