同一個頁面,在浏览器里正文、導航、评论都齐了,搜尋引擎拿到的初始 HTML 里却只有一個空容器标簽——這種情况在改版或前端框架升級之後很常见。搜尋引擎确實能执行一部分 JavaScript,但渲染要排队、要額外消耗资源,能直接讀到的内容,通常比渲染後才出現的内容更稳。這篇讲怎么判断自己的頁面是不是空壳,以及哪些東西應该直接寫進 HTML。
一、先確認蜘蛛到底拿到了什么
判断方式不复杂,關键是別用错工具。
- 看網頁源代碼,而不是開發者工具里的元素面板。元素面板展示的是脚本执行後的结果,源碼才是最初的 HTML,两者内容差得越多,依赖脚本的程度就越高。
- 用命令行抓一次,只看返回的 HTML 里有没有正文标题、段落文字和連結,不执行任何脚本。如果返回内容接近空白,說明首屏 HTML 基本没内容。
- 用搜尋後台的 URL 检查工具,對比渲染後的 HTML 與截图,看正文、導航是否都出現,以及渲染是否报错。
- 看服務器日誌,同一 URL 是否出現多次抓取:一次取初始 HTML,隔一段時間再来一次做渲染。重复抓取本身不一定是問题,但如果渲染那次经常被放弃,内容就等于没被抓到。
二、哪些内容最好直接寫在 HTML 里
不是所有模块都要求服務端輸出,優先級可以這样排:
- 文章的标题與正文主体、产品名稱與關键參數、頁面主标题與简介。
- 主導航、面包屑、分類入口、文章之間的相關阅讀連結。
- 分頁入口、上一篇下一篇、栏目列表的首屏若干條。
- 图片的替代文本、外鏈的目标地址。
评论、推荐流、彈窗表單、個性化推荐位這類次要模块,晚一点出現影响不大。
一個简單的判断标准:關掉 JavaScript 之後,頁面還剩多少對用戶有用的信息和可点的連結。剩下的越多,抓取和收錄就越省事。
三、容易踩空的几種寫法
- 内鏈用按钮或脚本跳轉。寫成按钮、並绑定点击事件去跳轉,抓取程序通常不會去点它;換成普通連結形式,带上目标地址,才是一條能被跟随的入口。
- 接口取資料後再拼頁面。首屏 HTML 里只有一個根节点,正文全部由接口返回後注入。用戶看到内容要等,抓取到的初始文档也几乎是空的。
- 骨架屏占位過久。骨架屏只是占位符,本身不含任何有效文字,如果内容長期不落地,多次抓取都只能看到同一套占位结构。
- 無限滚動没有可訪問的分頁地址。用戶能一直往下滑,抓取程序却找不到第二頁入口,列表尾部的内容就没有路径被發現。
- 懒加载图片用脚本換地址。图片放在 data 属性里、滚動时才寫入 src,早期抓取可能取不到图,图集類頁面的内容也容易残缺。
四、可行的折中办法
全站改成服務端渲染代價不小,也從不是唯一答案。比較務實的顺序是:
- 首屏關键内容與導航、内鏈服務端輸出,其余模块在客戶端补齐。
- 把接口請求提前,让正文在首次渲染时就能拿到資料,缩短空窗期。
- 列表頁保留传统的分頁地址,無限滚動只是交互上的增强,两種入口並存並不冲突。
- 图片懒加载同时保留原始地址,並在 HTML 中寫好替代文本。
- 重要連結避免依赖鼠标事件,用标准連結形式承载。
五、改完之後怎么驗證
- 關閉脚本再看一遍頁面,正文标题和主要連結是否還在。
- 用命令行抓取,確認返回 HTML 中能搜到正文里的獨特词组。
- 在搜尋後台對比渲染前後的 HTML,看是否有渲染报错或超时。
- 過一段時間看日誌,同一個 URL 是否還在被反复抓取却迟迟不更新。
前端渲染和抓取並不對立,問题往往出在“把什么都推到客戶端”。把對用戶和搜尋引擎都重要的那部分内容放回首屏 HTML,剩下的交给脚本去增强体驗,是成本最低也最容易長期维持的做法。