在很多情況下,一些網站的頁面或資源我們通常需要登錄才能 纔能看到。比如存取 GitHub 的個人設定頁面,如果不登錄是無法檢視的;比如 12306 買票提交訂單的頁面,如果不登錄是無法提交訂單的;再比如要發一條微博,如果不登錄是無法發送的。
我們之前學習的案例都是爬取的無需登錄即可存取的站點,但是諸如上面例子的情況非常非常多,那假如我們想要用爬蟲來存取這些頁面,比如用爬蟲修改 GitHub 的個人設定,用爬蟲提交購票訂單,用爬蟲發微博,能做到嗎?
答案是可以,這裏就需要用到一些模擬登錄相關的技術了。那麼本課時我們就先來了解模擬登錄的一些基本原理和實現吧。
我們要實現模擬登錄,那就得首先瞭解網站登錄驗證的實現。
登錄一般需要兩個內容,使用者名稱和密碼,有的網站可能是手機號和驗證碼,有的是微信掃碼,有的是 OAuth 驗證等等,但根本上來說,都是把一些可供認證的資訊提交給了伺服器。
比如這裏我們就拿使用者名稱和密碼來舉例吧。使用者在一個網頁表單裏面輸入了內容,然後點選登錄按鈕的一瞬間,瀏覽器用戶端就會向伺服器發送一個登錄請求,這個請求裏面肯定就包含了使用者名稱和密碼資訊,這時候,伺服器需要處理這些資訊,然後返回給用戶端一個類似「憑證」的東西,有了這個「憑證」以後呢,用戶端拿着這個「憑證」再去存取某些需要登錄才能 纔能檢視的頁面,伺服器自然就能「放行」了,然後返回對應的內容或執行對應的操作就好了。
形象地說,我們以登錄發微博和買票坐火車這兩件事來類比。發微博就好像要坐火車,沒票是沒法坐火車的吧,要坐火車怎麼辦呢?當然是先買票了,我們拿錢去火車站買了票,有了票之後,進站口查驗一下,沒問題就自然能去坐火車了,這個票就是坐火車的「憑證」。
發微博也一樣,我們有使用者名稱和密碼,請求下伺服器,獲得一個「憑證」,這就相當於買到了火車票,然後在發微博的時候拿着這個「憑證」去請求伺服器,伺服器校驗沒問題,自然就把微博發出去了。
那麼問題來了,這個「憑證「」到底是怎麼生成和驗證的呢?目前比較流行的實現方式有兩種,一種是基於 Session + Cookies 的驗證,一種是基於 JWT(JSON Web Token)的驗證,下面 下麪我們來介紹下。
我們在模組一瞭解了 Session 和 Cookies 的基本概念。簡而言之,Session 就是存在伺服器端的,裏面儲存了使用者此次存取的對談資訊,Cookies 則是儲存在使用者本地瀏覽器的,它會在每次使用者存取網站的時候發送給伺服器,Cookies 會作爲 Request Headers 的一部分發送給伺服器,伺服器根據 Cookies 裏面包含的資訊判斷找出其 Session 物件,不同的 Session 物件裏面維持了不同存取使用者的狀態,伺服器可以根據這些資訊決定返回 Response 的內容。
我們以使用者登錄的情形來舉例,其實不同的網站對於使用者的登錄狀態的實現可能是不同的,但是 Session 和 Cookies 一定是相互配合工作的。
梳理如下:
以上兩種情況幾乎能涵蓋大部分的 Session 和 Cookies 登錄驗證的實現,具體的實現邏輯因伺服器而異,但 Session 和 Cookies 一定是需要相互配合才能 纔能實現的。
Web 開發技術是一直在發展的,近幾年前後端分離的趨勢越來越火,很多 Web 網站都採取了前後端分離的技術來實現。而且傳統的基於 Session 和 Cookies 的校驗也存在一定問題,比如伺服器需要維護登錄使用者的 Session 資訊,而且不太方便分佈式部署,也不太適合前後端分離的專案。
所以,JWT 技術應運而生。JWT,英文全稱叫作 JSON Web Token,是爲了在網路應用環境間傳遞宣告而執行的一種基於 JSON 的開放標準。實際上就是每次登錄的時候通過一個 Token 字串來校驗登錄狀態。
JWT 的宣告一般被用來在身份提供者和服務提供者間傳遞被認證的使用者身份資訊,以便於從資源伺服器獲取資源,也可以增加一些額外的其他業務邏輯所必須的宣告資訊,所以這個 Token 也可直接被用於認證,也可傳遞一些額外資訊。
有了 JWT,一些認證就不需要藉助於 Session 和 Cookies 了,伺服器也無需維護 Session 資訊,減少了伺服器的開銷。伺服器只需要有一個校驗 JWT 的功能就好了,同時也可以做到分佈式部署和跨語言的支援。
JWT 通常就是一個加密的字串,它也有自己的標準,類似下面 下麪的這種格式:
eyJ0eXAxIjoiMTIzNCIsImFsZzIiOiJhZG1pbiIsInR5cCI6IkpXVCIsImFsZyI6IkhTMjU2In0.eyJVc2VySWQiOjEyMywiVXNlck5hbWUiOiJhZG1pbiIsImV4cCI6MTU1MjI4Njc0Ni44Nzc0MDE4fQ.pEgdmFAy73walFonEm2zbxg46Oth3dlT02HR9iVzXa8
可以發現中間有兩個「.」來分割開,可以把它看成是一個三段式的加密字串。它由三部分構成,分別是 Header、Payload、Signature。
這三部分通過「.」組合起來就形成了 JWT 的字串,就是使用者的存取憑證。
所以這個登錄認證流程也很簡單了,使用者拿着使用者名稱密碼登錄,然後伺服器生成 JWT 字串返回給用戶端,用戶端每次請求都帶着這個 JWT 就行了,伺服器會自動判斷其有效情況,如果有效,那自然就返回對應的數據。但 JWT 的傳輸就多種多樣了,可以放在 Request Headers,也可以放在 URL 裡,甚至有的網站也放在 Cookies 裡,但總而言之,能傳給伺服器校驗就好了。
好,到此爲止呢,我們就已經瞭解了網站登錄驗證的實現了。
好,瞭解了網站登錄驗證的實現後,模擬登錄自然就有思路了。下面 下麪我們也是分兩種認證方式來說明。
基於 Session 和 Cookies 的模擬登錄,如果我們要用爬蟲實現的話,其實最主要的就是把 Cookies 的資訊維護好,因爲爬蟲就相當於用戶端瀏覽器,我們模擬好瀏覽器做的事情就好了。
那一般情況下,模擬登錄一般可以怎樣實現呢,我們結合之前所講的技術來總結一下:
以上介紹的就是一些常用的爬蟲模擬登錄的方案,其目的就是維護好用戶端的 Cookies 資訊,然後每次請求都攜帶好 Cookies 資訊就能實現模擬登錄了。
基於 JWT 的真實情況也比較清晰了,由於 JWT 的這個字串就是使用者存取的憑證,那麼模擬登錄只需要做到下面 下麪幾步即可:
如果爬蟲要求爬取的數據量比較大或爬取速度比較快,而網站又有單賬號併發限制或者存取狀態檢測並反爬的話,可能我們的賬號就會無法存取或者面臨封號的風險了。這時候一般怎麼辦呢?
我們可以使用分流的方案來解決,比如某個網站一分鐘之內檢測一個賬號只能存取三次或者超過三次就封號的話,我們可以建立一個賬號池,用多個賬號來隨機存取或爬取,這樣就能數倍提高爬蟲的併發量或者降低被封的風險了。
比如在存取某個網站的時候,我們可以準備 100 個賬號,然後 100 個賬號都模擬登錄,把對應的 Cookies 或 JWT 存下來,每次存取的時候隨機取一個來存取,由於賬號多,所以每個賬號被取用的概率也就降下來了,這樣就能避免單賬號併發過大的問題,也降低封號風險。
以上,我們就介紹完了模擬登錄的基本原理和實現以及優化方案,希望你可以好好理解。