網路爬蟲陷阱:原因、解決方案與預防 - 開發者深度剖析
目錄
網路爬蟲陷阱入門
當搜尋引擎</a>爬蟲或SEO</a>蜘蛛開始抓取大量不會帶來新的獨特內容</a>或連結的URL時,就會發生爬蟲陷阱。爬蟲陷阱的問題在於它們消耗了搜尋引擎</a>為每個網站分配的爬行預算</a>。一旦預算</a>用完,搜尋引擎</a>就沒有時間去爬取該網站上真正有價值的頁面。<br/><br/>這可能導致流量顯著減少。這在基於數據庫的網站上是一個常見問題,因為大多數開發人員甚至不知道這是一個嚴重的問題。當他們從最終用戶的角度評估一個網站時,它運作良好,他們看不到任何問題。<br/><br/>那是因為最終用戶在點擊鏈接時是有選擇性的,他們並不會跟隨頁面上的每個鏈接。
優勢 | 劣勢 | |
---|---|---|
機會 |
|
|
威脅 |
|
|
被網站檢測到並封鎖或限制存取
讓我們來看一下爬蟲如何</a>透過在HTML</a>代碼中找到並跟隨連結來導航網站。以下是一個基於Scrapy的簡單示例爬蟲的程式碼,我從他們的主頁上改編而來。你可以根據他們的教程自由地學習</a>如何</a>建立自定義的爬蟲。<br/><br/>第一個for迴圈從"最新文章"部分抓取所有文章區塊,第二個迴圈只跟隨我用箭頭標出的"下一頁"連結。當你撰寫這樣的選擇性爬蟲時,可以輕鬆地跳過大部分爬蟲陷阱!你可以將程式碼保存到本地檔並從命令列運行該爬蟲,像這樣: $ scrapy runspider sejspider.py 或者從腳本或Jupyter筆記本運行它。以下是該爬蟲執行時的示例日誌:傳統的爬蟲會提取並跟隨頁面上的所有連結。<br/><br/>有些連結是相對路徑,有些是絕對路徑,有些會指向其他網站,而大多數則會指向站內的其他頁面。爬蟲需要在爬取它們之前將相對URL轉換為絕對URL,並標記已訪問過的連結以避免重複訪問。搜尋引擎</a>爬蟲比這更加複雜。<br/><br/>它被設計為分佈式爬蟲。這意味著對你的站點的爬取不是來自一台機器/IP,而是來自多個機器/IP。這個主題超出了本文的範圍,但你可以閱讀Scrapy文檔來瞭解如何</a>實現分佈式爬蟲並深入瞭解更多細節。<br/><br/>既然你已經看到了爬蟲程式碼並理解了它的工作原理,讓我們探索一些常見的爬蟲陷阱,看看為什麼爬蟲會中招。
會話識別碼
現今大多數網站使用HTTP cookies來識別使用者,如果使用者關閉了cookies,則無法使用該網站。然而,仍有許多網站採用另一種辨識使用者的方式:會話ID。這個ID對於每個網站訪客是唯一的,並自動嵌入到所有頁面的URL中。<br/><br/>當搜尋引擎</a>爬蟲爬取頁面時,所有URL都會包含會話ID,使得URL變得唯一且看似具有新內容</a>。但要注意的是,搜尋引擎</a>爬蟲是分散式的,因此請求會來自不同的IP位址。這導致產生更多唯一的會話ID。<br/><br/>我們希望搜索爬蟲能夠爬取:當會話ID作為URL參數時,這個問題很容易解決,因為可以在URL參數設置中阻止它。但是,如果會話ID嵌入到實際URL路徑中呢?是的,這是可能且有效的。基於企業級Java Bean規範的Web服務器通常將會話ID附加在路徑中, 例如: ;jsessionid。<br/><br/>你可以輕易找到仍然在URL中包含這個的網站。在路徑中包含這個參數時,無法阻止它。你需要在源頭上修正它。<br/><br/>現在,如果你正在撰寫自己的爬蟲程式,你可以使用以下代碼輕鬆跳過此問題 😉
分面導航
在現代的電子商務</a>網站上,分面式或導引式導航是非常常見的,但也是最常見的爬蟲陷阱來源。問題在於一般使用者只會做出少數選擇,但當我們指示爬蟲抓取這些連結並跟隨它們時,它會嘗試每一種可能的組合。要爬取的URL數量變成了一個排列組合問題。<br/><br/>在上面的畫面中,我們有X個可能的排列組合。傳統上,你可以使用JavaScript生成這些排列組合,但由於Google可以執行和爬取它們,這已經不夠了。更好的方法是將參數添加為URL片段。<br/><br/>搜尋引擎</a>爬蟲會忽略URL片段。因此,上述程式碼將被重寫如下所示:以下是將特定參數轉換為片段的程式碼。我們經常看到一些可怕的分面式導航實現方式將篩選URL參數轉換成路徑,這使得通過查詢字串進行任何篩選幾乎不可能。<br/><br/>例如,而不是/category?color=blue,你會得到/category/color=blue/。
錯誤的相對連結
我曾經遇到很多相對URL的問題,所以我建議客戶始終使用絕對URL。後來我意識到這是一個極端的措施,但讓我用代碼來展示為什麼相對連結可能會引起許多爬蟲陷阱。正如我之前提到的,當爬蟲發現</a>相對連結時,它需要將它們轉換為絕對連結。<br/><br/>為了轉換成絕對連結,它使用源URL作為參考。以下是將相對連結轉換為絕對連結的代碼。現在,看看當相對連結格式不正確時會發生什麼情況。<br/><br/>以下代碼顯示了生成的絕對連結。接下來就是爬蟲陷阱出現的地方了。當我在瀏覽器中打開這個假URL時,我並沒有收到404錯誤,這樣爬蟲就無法知道該放棄該頁面並停止跟隨其上的任何連結。<br/><br/>而是得到了一個柔性404錯誤,從而使陷阱開始運作。當爬蟲嘗試生成絕對URL時,我們在頁腳中的錯誤連結又會增長</a>。爬蟲將繼續進行此過程,假URL將不斷增長</a>,直到達到Web服務器軟件或CDN支持的最大URL限制。<br/><br/>這取決於系統。例如,IIS和Internet Explorer不支持超過2,048-2,083</a>個字元長度的URL。有一種快速且簡單或冗長且痛苦的方法可以檢測此類爬蟲陷阱。<br/><br/>你可能已經熟悉冗長而痛苦的方法:運行SEO</a>爬蟲幾個小時直到它碰到陷阱。通常你會知道找到了一個陷阱,因為如果你在桌面機器上運行它,它就會耗盡內存;如果你使用基於雲端的工具</a>,在小型站點上就會發現</a>數以百萬計的URL。快速且容易的方法是查看服務器日誌中是否存在414狀態碼錯誤。<br/><br/>大多數符合W3</a>C標準的Web服務器在URL請求長度超過其限制時將返回414錯誤。如果Web服務器未報告414錯誤,你可以通過測量日誌中請求的URL長度,並過濾掉超過2000個字元的URL。以下是執行這兩種方法的代碼。<br/><br/>還有一種特別難以檢測到的缺少尾部斜線的變異情況。這發生在你從代碼復制粘貼到文書處理軟件時,它們會替換引號字元。對人眼來說,引號看起來是一樣的,除非你仔細觀察。<br/><br/>讓我們看看當爬蟲將這個看似正確的相對URL轉換為絕對URL時會發生什麼情況。
快取破壞
緩存破解是開發人員用於強制CDN(內容</a>傳遞網路)使用其託管檔的最新版本的一種技術。這種技術需要向您要“破解”的頁面或頁面資源添加一個唯一識別碼,以通過CDN緩存進行訪問。當開發人員使用一個或多個唯一識別碼值時,它會創建額外的URL來爬取,通常是圖像、CSS和JavaScript檔,但這通常不是一個大問題。<br/><br/>最大的問題出現在他們決定使用隨機唯一識別碼、頻繁更新頁面和資源,並讓搜尋引擎</a>爬取所有檔變體時。以下是示例代碼。您可以在伺服器日誌中檢測到這些問題,在下一節中我將介紹如何</a>編寫代碼進行檢測。<br/><br/>
版本化頁面快取與圖像重設大小
類似於快取破解的問題,像MageWorx這樣的公司開發的靜態頁面快取外掛程式也存在一個奇怪的問題。對於我們的某個客戶來說,他們的Magento外掛程式在客戶進行任何更改時都會保存不同版本的頁面資源。當該外掛程式自動調整圖片以適應不同設備時,這個問題就變得更加嚴重了。<br/><br/>當他們最初開發該外掛程式時,可能並沒有出現這個問題,因為Google並未試圖積極爬取頁面資源。然而,現在搜尋引擎</a>爬蟲也會爬取頁面資源,並且會抓取快取外掛程式生成的所有版本。我們有一位客戶,在那裡爬行速率是站點大小的100倍,其中70%的爬行請求是針對圖片。<br/><br/>只能通過查看日誌才能檢測到此類問題。為了更好地說明這個問題以及如何</a>識別它,我們將生成假的Googlebot請求,針對隨機快取圖片。這是初始化代碼:這是生成假日誌項目的循環。<br/><br/>接下來,讓我們使用pandas和matplotlib來識別此問題。該圖顯示了下麵的圖像。該圖顯示了每天的Googlebot請求量。<br/><br/>它類似於舊版Search Console中的爬行統計功能。正是這份報告促使我們更深入地研究日誌檔。在將Googlebot請求轉換為Pandas數據框後,可以相對容易地找出問題所在。<br/><br/>以下是如何</a>按日期篩選出爬行高峰期之一,並按頁面類型和檔擴展名進行分解的方法。
長重定向鏈條和迴圈
一種浪費爬蟲預算</a>的簡單方法是擁有非常長的重定向鏈,甚至出現循環。這通常是由於程式碼錯誤導致的。讓我們編寫一個例子來展示一個造成循環的重定向鏈,以更好地理解它們。<br/><br/>當您在Chrome中打開第一個URL時,會發生以下情況。您也可以在Web應用程式日誌中看到這條鏈。當您要求開發人員實施重寫規則時:從HTTP轉換為HTTPS、將URL小寫化、使URL對搜尋引擎</a>友好等,他們會級聯每個規則,使每個規則都需要單獨的重定向而不是從源到目標的單一重定向。<br/><br/>重定向鏈容易檢測,如下所示的代碼所示。一旦識別出問題代碼,修復起來也相對容易。始終從源頭重新導向到最終目的地即可解決重定向鏈問題。<br/><br/>
行動版/桌面版重定向連結
有一種有趣的轉向方式是某些網站用來幫助使用者強制顯示手機版或桌上出版網站。有時它會使用URL參數來指示所需的網站版本,這通常是安全可靠的方法。然而,cookie和用戶代理檢測也很流行,但這可能導致循環問題,因為搜尋引擎</a>爬蟲不會設置cookie。<br/><br/>下面這段程式碼展示了正確運作的方式。而下面這段則展示了錯誤假設(依賴於HTTP cookie存在)所導致的問題。
循環代理URLs
最近我們遇到了一個不尋常的情況,但我預計隨著越來越多服務轉移到像Cloudflare這樣的代理服務後,這種情況會越來越常見。你可能會有多次代理的URL形成一個鏈條,就像重定向發生的那樣。你可以把被代理的URL視為在服務器端重定向的URL。<br/><br/>在瀏覽器中,URL不會改變,但內容</a>會改變。要查看被代理URL循環,你需要檢查你的服務器日誌。我們在Cloudflare上有一個應用程式,用於通過API調用後端以獲取SEO</a>更改。<br/><br/>我們團隊最近引入了一個錯誤,導致我們的API調用被代理到自身,結果產生了一個難以檢測到的循環。我們使用了@chasers開發的非常實用的Logflare應用程式來實時查看我們的API調用日誌。下麵是正常調用的示例。<br/><br/>以下是循環/遞歸調用示例,在解碼文本時我發現</a>了數百個鏈式請求。我們可以使用檢測錯誤的相對連結時使用的相同技巧。我們可以按照狀態碼414或請求長度進行篩選。<br/><br/>大多數請求的長度不應該超過2,049個字元。你可以參考我們用於檢測錯誤重定向的代碼。
神奇的URLs + 隨機文本
另一個例子是當URL中包含可選文本且只需要一個ID來提供內容</a>時。一般來說,這並不是什麼大問題,除非URL可以與網站內的任何隨機、不一致的文本連結起來。例如,當產品URL經常更改名稱時,搜尋引擎</a>需要爬取所有變體。<br/><br/>如果我用短文本作為產品描述跟隨連結到產品113</a>7649-4,我會載入產品頁面。但是,你可以看到規範與我請求的頁面不同。基本上,在產品和產品ID之間你可以輸入任意文本,並載入相同的頁面。<br/><br/>規範解決了重複內容</a>的問題,但爬行空間可能很大,這取決於產品名稱更新次數的多少。為了跟蹤此問題的影響,您需要將URL路徑拆分為目錄,並按其產品ID對URL進行分組。以下是代碼示例以及示例輸出。<br/><br/>
連結到動態生成的內部搜索
有些現場搜索供應商通過使用大量關鍵詞進行搜索並將搜索URL格式化為常規URL,來幫助創建基於“新”關鍵詞的內容</a>。一般情況下,少數此類URL不是很重要,但當您將其與大量關鍵詞列表結合在一起時,就會出現類似於我之前提到的篩選導航問題。太多的URL導致大部分內容</a>相同。<br/><br/>可以用來檢測這些URL的一個技巧是查看列表的class ID是否與執行常規搜索時的列表相匹配。在上面的例子中,我看到了一個class ID "sli_phrase" ,這表明該網站正在使用SLI Systems來驅動他們的搜索。我將把檢測它的代碼留給讀者自己去完成。<br/><br/>
如何在發布代碼到生產前捕捉爬蟲陷阱
現代的開發團隊通常使用一項技術稱為持續整合(continuous integration)來自動化高品質程式碼的交付至生產環境。自動測試是持續整合工作流程</a>中的重要組成部分,也是我們在本文中提到的腳本應用的最佳場所,用於捕捉陷阱。其概念是一旦偵測到爬蟲陷阱,就會停止將程式碼部署至生產環境。<br/><br/>您可以使用相同方法來撰寫測試以解決其他關鍵的 SEO</a> 問題。CircleCI 是這個領域中的其中一家供應商,下面您可以看到我們其中一次建置的範例輸出。
相關數據:
- 67%的網站使用爬蟲技術進行資料收集 來源: brightdata
- 每天有超過1.5億次的爬蟲攻擊事件 來源: imperva
- 2019年全球網路爬蟲攻擊增長了24% 來源: akamai technologies
- 美國每年因爬蟲攻擊而損失超過100億美元 來源: shape security
- 英國企業每年因爬蟲攻擊而損失超過4億英鎊 來源: distil networks
如何在事後診斷陷阱
目前最常見的方法是在損害發生後才捕捉到爬蟲陷阱。通常你會運行一個SEO</a>爬蟲來進行探索,如果永遠都無法結束,那麼很可能是陷阱。使用Google搜索和像site:這樣的操作符檢查,如果有太多索引頁面</a>,就表示可能有陷阱。<br/><br/>你還可以使用Google搜索控制台中的URL參數工具</a>來檢查監視的URL數量是否過多。只有通過查找重複模式在服務器日誌中才能找到這裡提到的許多陷阱。當你看到大量重複的標題或元描述時,也可以檢查是否存在陷阱。<br/><br/>另外要檢查的是內部連結</a>數量是否比網站上實際存在的頁面更多。