做入口頁的时候,很多人會在目标連結後面加一段以 # 開头的内容,比如 https://example.com/post#source=pool1,用来区分不同入口带来的訪問。問题是:搜尋蜘蛛抓到這條連結时,請求的到底是带 # 的完整地址,還是只有 # 前面那一截?答案是明确的——# 後面的内容不會進入 HTTP 請求。
锚点為什么發不到服務器
URL 标准里,# 及其後面的部分叫 fragment(片段标识符)。它的设計目的是让浏览器在已经拿到的文档内部做定位,比如跳到某個小标题。這個動作完全在客戶端完成,服務器從头到尾看不到它。
搜尋蜘蛛遵循同一套規則:解析連結、去掉 fragment、用剩下的部分發請求。所以無论入口頁怎么寫锚点,蜘蛛對服務器的請求都只有路径加查询參數。
蜘蛛實际請求的地址長什么样
- 入口頁寫 https://example.com/a#part1 → 蜘蛛請求 https://example.com/a
- 同一頁再寫 https://example.com/a#part2 → 仍然只請求 https://example.com/a
- 寫 https://example.com/a?#part3(問号後直接跟 #)→ 同样只請求 /a
- 只寫 href="#top" 這類纯锚点 → 指向目前頁面自身,不是一個新 URL
也就是说,锚点既不改變服務器收到的路径,也不改變蜘蛛的抓取次數。它只影响浏览器渲染时的定位行為。
三個常见的誤用
用 # 传来源參數
#source=pool1 只有頁面里的脚本能讀到,服務端訪問日誌里看不到。如果来源統計依赖日誌,這類參數等于没寫,白忙一场。
指望同一 URL 配不同锚点被当成多個頁面
有人给同一個目标 URL 挂上 #a、#b、#c,想让蜘蛛“多發現几個地址”。實际它看到的始终是同一個 URL,不會产生額外的發現或抓取。
用 # 掩盖真實參數再靠脚本跳轉
前端讀取 # 後再用脚本跳到真實地址,這属于動態注入連結。能否被發現,取决于抓取端是否执行脚本、渲染是否完成,和直接给静態連結完全不是一回事。
想区分来源,可以怎么做
- 用不同路径:入口頁指向 /lp/pool1/ 這類獨立路径,服務端可統計。但要注意別批量生成内容雷同的頁面,否則統計清楚了、頁面质量却下去了。
- 用查询參數:?from=pool1 服務端可见。風險是同一目标 URL 挂太多不同參數,可能被当成多個地址反复抓取,最好配合 canonical 收敛,或让 robots.txt 挡掉無意义的參數组合。
- 看日誌里的来源信息:蜘蛛抓取目标 URL 时通常带着来源頁字段,入口頁本身也可以靠這個反推,不必把參數塞進連結。
- 用中間跳轉:入口頁放一個带參數的中間地址,由它跳轉到最终目标,參數留在跳轉前的日誌里,最终頁保持干净。
几個容易忽略的邊界
href="#" 和 href="javascript:;"
這類寫法没有指向任何真實地址,蜘蛛不會把它当成可抓連結,也不會因此發現別的内容。放在入口頁里只會让頁面看着連結很多,實际是空的。
前端路由里的 #
#/list 這種路由形式,蜘蛛請求的仍然是 # 之前的部分,路由内容要靠脚本渲染。能不能被發現取决于抓取端是否渲染 JS,不取决于锚点本身。
跳轉响應里带 #
如果服務器返回的跳轉地址里带了 fragment,浏览器會把它保留下来,但服務器端日誌依然只有路径部分。別指望用這種方式在日誌里留下来源标记。
上线前的自检清單
- 目标頁是否只有讀 # 後面的内容才能正常展示?如果是,蜘蛛看到的很可能是空頁或残缺頁。
- 来源統計是不是寫在了 # 里?若是,服務端資料會缺失。
- 同一目标 URL 是否因為參數被拆成很多個地址?需要收敛或加 canonical。
- 入口頁里的 href="#" 是否被誤当成有效連結?建议清理掉。
锚点解决的是文档内定位問题,不是連結唯一性或来源追踪問题。把它当成地址的一部分来用,得到的往往是和预期相反的統計结果。