現在的頁面越来越多内容由 JavaScript 拼出来:導航、列表、分頁、相關推荐,在浏览器里看着都是能点的連結,但蜘蛛第一次請求拿到的 HTML 里,可能只有一段脚本和一個空容器。連結在不在 HTML 里,直接决定蜘蛛能不能顺着走。
蜘蛛看到的 HTML,和你看到的可能不一样
抓取通常分两步:先取回 HTML 源碼,再决定要不要执行脚本做渲染。第二步不是必然發生,也不是即时發生。
- 渲染有队列:頁面要先排队,才轮得到执行脚本,連結的發現時間會被推後。
- 预算有限:站内重要、抓取频繁的頁面更容易被渲染,邊缘頁面可能只取源碼不渲染。
- 引擎之間有差异:不同搜尋引擎执行脚本的能力不一样,只依赖渲染,等于把發現的主動權交给了對方。
所以判断标准可以很简單:這條連結有没有出現在服務端輸出的 HTML 里。
几種常见的寫法,蜘蛛能走到哪一步
- a 标簽加真實 href:最稳,源碼里就有地址,不依赖渲染。
- div 加点击事件再跳轉:源碼里没有地址,多數情况下蜘蛛不會跟。
- onclick 里寫跳轉:同上,属于交互行為,不是連結。
- hash 路由:地址里的井号部分一般不會被当成獨立 URL,容易只發現一個入口頁。
- 前端渲染的列表:源碼里是空容器,要靠渲染才能看到條目,能不能被發現取决于渲染是否执行。
- 滚動加载或按需加载:不触發加载條件就不产生請求,後面的内容等于不存在。
- 分頁按钮没有 href:蜘蛛只能停在第一頁。
不用猜:三個能自己驗證的办法
- 關掉脚本直接看頁面源碼。列表里有多少條、有没有指向詳情頁的地址,一眼就能看清。這一步看到的内容,就是蜘蛛第一眼看到的内容。
- 對照訪問日誌。看列表頁被請求之後,詳情頁是否紧接着出現請求。如果列表頁被抓了、詳情頁長期没有動静,問题多半出在連結没有被輸出。
- 小范围改動後再观察。把某一類列表的連結改成服務端輸出,再看這一批 URL 的發現速度和抓取數量有没有變化。
把關键路径放回 HTML
不需要把所有東西都改成服務端渲染,優先保證這几處:主導航、分類列表的第一屏、分頁的前後頁、面包屑、正文里的站内引用。
渲染是补救手段,不是連結的替代品。連結的發現,最好在第一次請求时就完成。
渲染出来的連結也要注意细节
- 連結尽量用真實可訪問的地址,別用脚本函數代替跳轉。
- 分頁保留固定的參數地址,让蜘蛛能一頁頁往後走。
- 异步加载出来的新内容要有稳定的 URL,別只存在于目前會话里。
- 站点地图和站内連結各管一段:地图负责把 URL 交出去,内鏈负责把路径铺出来,两者不能互相顶替。
可以先挑一個栏目做小實驗:把列表連結改成服務端輸出,同时把對應地址放進站点地图,然後连續观察两三周的抓取记錄。改動带来的差別,往往比任何猜测都清楚。