URL 里常见一個井号,後面跟着一截内容。對普通用戶来说,它常常只是“跳到頁面某個位置”;對搜尋蜘蛛来说,它基本等于不存在。理解這一点,能避免很多“連結明明放在頁面上,蜘蛛却始终没来”的困惑。
井号後面不參與請求
浏览器發起請求时,HTTP 請求行里只有协议、域名、路径和查询串,井号及其後面的片段标识符由浏览器本地處理,不會發送给服務器。所以 example.com/a#part2 和 example.com/a 在服務器看来是同一個請求,日誌里记錄的也只是井号之前的那一段。
- 蜘蛛抓取 a 頁面一次,就等于覆盖了它所有的锚点變体;
- Sitemap 里寫带锚点的地址,相当于重复提交同一頁;
- 用锚点区分的内容区块,不會形成獨立 URL。
锚点内鏈還有没有用
有用,但作用在“頁内跳轉”和“语义上下文”上,而不是产生新 URL。目錄、導航里的锚点連結能让蜘蛛更清楚地理解這一頁的结构,锚文本里的關鍵詞也能帮它判断這一段在讲什么。前提是目标内容真實存在于 HTML 里。
如果“展開更多”是靠点击後异步加载,锚点跳到的地方可能只是一個空容器,蜘蛛顺着跳過去也讀不到内容。這類内容最好預設渲染在 HTML 中,或者提供一個可直達的獨立 URL。
hash 路由是另一種情况
前端路由常见形如 /#!/detail/123 或 /#/detail/123 的寫法。服務端收到的永遠是站点根路径,返回同一個壳頁面。蜘蛛看到的是同一份 HTML,抓十次、一百次都一样,具体條目自然無法被發現。這既浪費抓取资源,也让大量内容停留在“不可發現”的狀態。
可行的調整方向:
- 改用 History API,把路由映射成真實路径,服務端對每個路径返回對應内容;
- 或者保留前端路由,但做服務端渲染或预渲染,让蜘蛛拿到的 HTML 里就有内容和連結;
- 關键栏目再补一份静態可抓路径,例如列表頁和詳情頁的服務端版本。
几個排查動作
- 翻日誌时,確認蜘蛛請求的路径里是否出現過井号,正常情况不该出現;
- 用命令行工具直接請求带井号的地址,看返回内容是否與预期一致;
- 检查 Sitemap 和内鏈,把带锚点的地址替換為規范的頁面地址;
- 检查是否存在 href="javascript:void(0)" 這類不产生請求的連結,它們對 URL 發現没有帮助。
锚点不是連結的替代品。要么给出一個真實的、服務端能响應的地址,要么就接受這部分内容暂时不會被獨立發現。
把“内容存在”和“内容可被發現”分開看,很多抓取問题會變得简單:蜘蛛只能走它能請求到的地址。井号後面的東西,交给浏览器就可以了。