整理投放連結时经常會碰到带 # 的 URL,比如頁面内的锚点定位 .../help#step3,或者單頁應用里的 .../#/detail/1001。這類連結投進蜘蛛池或提交入口後,日誌里往往看不到预期的抓取,于是怀疑投放没生效。多數情况下,問题不是出在蜘蛛池,而是 # 号後面的内容並不參與 URL 识別。
一、先分清 # 後面是锚点還是路由
同样是 #,含义差別很大:
- 頁内锚点:# 後面是某個元素的 id,打開後浏览器滚動到對應位置,頁面内容與不带 # 的版本基本一致。
- hash 路由:# 後面是前端路由路径,頁面内容由 JS 根據這段路径渲染出来,服務端通常返回同一個 HTML 骨架。
- 带參數的 hash:類似 #!key=value 的寫法,多出現在早期單頁應用,本质仍归到上面第二類。
二、搜尋蜘蛛看到的是什么
抓取时,客戶端向服務器發起的請求一般只包含 # 之前的部分。也就是说,請求 .../help#step3 和請求 .../help,在服務器日誌里是同一條记錄,日誌里不會出現 #step3。蜘蛛能拿到的,是不带 # 的那份响應。
對于 hash 路由頁面,如果搜尋引擎愿意渲染 JS,理论上能看到 # 後面那段路径對應的内容;但在 URL 层面,带 # 和不带 # 通常仍被当作同一個地址處理,不會自動變成两個獨立頁面。
把带 # 的連結当作“新 URL”来投放或提交,是常见的誤操作:蜘蛛去訪問的仍然只是 # 前面的那個地址。
三、投放這類連結时會遇到什么
- 日誌里只能看到不带 # 的請求,誤以為“没抓到”,其實是地址被截断了。
- 如果 # 前面的地址已经被抓過,重复投放往往不會带来新的抓取行為。
- 用带 # 的連結做外部入口,能传递的發現價值會打折,因為對外可识別的還是前缀地址。
- 統計时把 #/a、#/b 当作两個頁面,容易高估覆盖量,實际只對應一個可抓地址。
四、希望 hash 路由頁被發現,可以這样做
- 能用真實路径就用真實路径,把 #/detail/1001 改成 /detail/1001,让每個内容有獨立的可請求地址。
- 改為真實路径後,服務端要為该路径返回可讀内容,或至少做预渲染、服務端渲染,避免返回空壳。
- 站内連結统一使用不带 # 的規范地址,减少同一内容出現多種寫法。
- 确實要保留 hash 路由的,至少让不带 # 的入口頁可正常抓取,並在頁面里以普通連結形式列出可訪問的目标地址。
- 提交 sitemap 或投放列表时,使用去掉 # 及其後内容的規范 URL。
五、排查时可以先確認三件事
- 服務器日誌里出現的地址,是带 # 的還是被截断後的版本。
- 同一個 # 前缀地址,是否已经有過抓取记錄。
- 目标内容是否需要 JS 渲染才能出現,未渲染时頁面里有没有可跟随的連結。
把這三点確認清楚,基本就能判断問题出在 URL 寫法還是抓取环节。URL 结构規范一些,蜘蛛發現新頁面的路径也會更顺,但具体抓取和收錄仍由搜尋引擎决定,無法通過投放来保證。