入口頁里的連結寫起来很简單,但 URL 里多一個 # 或者多几個 ?utm_xxx 參數,搜尋蜘蛛看到的東西就可能和你以為的不一样。這两類符号的處理逻辑几乎相反,混在一起谈很容易得出错誤结论。
先说 # :锚点後面的内容通常不參與抓取识別
URL 里 # 之後的部分叫片段标识符(fragment),它本来就不是给服務器看的,浏览器請求时不會把它發出去。對搜尋蜘蛛来说,情况類似:
- http://a.com/page#top 和 http://a.com/page#section2,一般被当成同一個 URL
- 服務器日誌里通常看不到 # 後面的内容,因為這部分不會進入 HTTP 請求行
- 入口頁只放带锚点的連結,目标 URL 依然可能被發現,只是被發現的是去掉锚点後的那個地址
也就是说,想用锚点来区分同一個頁面上的不同位置,對搜尋抓取是没有意义的。真正决定抓取的是锚点前面的路径和參數。如果目标頁面是單頁應用、靠 # 路由切換内容,那更需要留意:搜尋蜘蛛看到的很可能只是那個 HTML 外壳。
再说 ? :查询參數是 URL 的一部分,情况正好相反
查询參數會随請求發给服務器,属于 URL 的组成部分。搜尋蜘蛛一般會把带不同參數的地址当成不同 URL,比如:
- ?utm_source=xxx&utm_medium=xxx
- ?ref=1
- ?from=spider
同一個目标頁面,如果在入口頁里用十几種參數拼出十几條連結,就可能被当成十几個地址。结果是抓取预算被摊薄,同一個内容重复抓取,真正想被發現的頁面反而排到後面。參數越多、组合越随意,這種浪費越明顯。
參數很多时,搜尋蜘蛛不一定全抓
搜尋引擎對參數 URL 通常有自己的取舍策略,常见做法包括:按規則合並相似參數、只抓其中一部分、或者干脆降低這類地址的優先級。所以你可能看到入口頁里寫了 50 條連結,日誌里只来了 8 條請求。這不一定代表入口頁失效,而是對方在按自己的节奏篩選。
反過来说,如果你的目标是让某個具体頁面被尽快發現,就不要把它的地址包装成一堆带參數的變体,那样只會让發現路径變模糊。
實操上怎么减少無意义的重复發現
- 入口頁里指向同一目标的連結,參數寫法保持统一。不要一會儿带 utm、一會儿不带、一會儿又換成 ref,同一個目标只用一種干净形式。
- 把統計參數交给前端脚本拼接,不要寫死在 HTML 的 a 标簽里。抓取到的是静態 HTML,前端拼的參數通常不會被当成連結地址收錄。
- 用 canonical 指向不带參數的主版本。注意這是建议而非命令,搜尋引擎可以忽略,所以它能减轻問题,但不能替代前两條。
- 必要时在 robots.txt 里屏蔽特定參數模式,或在站長平台使用 URL 參數相關工具做统一處理。屏蔽前先確認這個词组不會誤伤正常頁面。
- 内鏈和 sitemap 只提交干净版本,让主要的發現入口保持一致。
怎么驗證你的入口頁實际被發現了哪些 URL
- 看服務器日誌里的請求行,重点留意 query string 部分,不要只看路径
- 用站長平台的抓取統計或 URL 检查功能,看對方實际记錄的地址形態
- 把日誌里去重後的 URL 數量,和入口頁里實际寫的連結數量做對比,差值往往就藏着參數問题
別只看入口頁寫了多少條連結,要看服務器實际收到了多少條不同的請求 URL。两條連結在頁面上看起来不一样,在日誌里可能就是同一個地址;反過来,看起来一样的頁面,可能已经變成十几條地址。
几個容易忽略的细节
- 參數顺序不同(?a=1&b=2 與 ?b=2&a=1)通常被视為不同 URL,入口頁生成的連結最好固定顺序
- 大小寫敏感的參數值也會造成分裂,例如 ?id=abc 與 ?id=ABC
- 目标 URL 结尾带不带斜杠,很多时候是两個地址,入口頁里保持一致即可
- 如果入口頁連結里同时出現 # 和 ?,比如 page?p=2#comment,抓取识別一般以 page?p=2 為准
這些都不是什么高深技巧,只是把 URL 寫得干净一致。入口頁的作用是把路径铺清楚,而不是制造一堆近似的地址让搜尋蜘蛛自己去猜。把參數和锚点這两件事分清楚,再用日誌驗證一次,通常就能知道問题出在哪一步。