小白學 Python 爬蟲(10):Session 和 Cookies
人生苦短,我用 Python
前文傳送門:
小白學 Python 爬蟲(1):開篇
小白學 Python 爬蟲(2):前置準備(一)基本類庫的安裝
小白學 Python 爬蟲(3):前置準備(二)Linux基礎入門
小白學 Python 爬蟲(4):前置準備(三)Docker基礎入門
小白學 Python 爬蟲(5):前置準備(四)資料庫基礎
小白學 Python 爬蟲(6):前置準備(五)爬蟲框架的安裝
小白學 Python 爬蟲(7):HTTP 基礎
小白學 Python 爬蟲(8):網頁基礎
小白學 Python 爬蟲(9):爬蟲基礎
引言
先說一個題外話,今天老司機翻車了,內容小編今天來不及寫了,後面會整理下,分享給大家。
在介紹 Session 和 Cookies 之前,先介紹一個另外的概念 —— 靜態網頁和動態網頁。
靜態網頁
靜態網頁就是我們上一篇寫的那種 html 頁面,字尾為 .html
的這種檔案,直接部署到或者是放到某個 web 容器上,就可以在瀏覽器通過連結直接訪問到了,常用的 web 容器有 Nginx 、 Apache 、 Tomcat 、Weblogic 、 Jboss 、 Resin 等等,很多很多。
如果說要舉例子的話那麼小編的個人部落格站:https://www.geekdigging.com/ 就是一個純粹的靜態網頁。
這種網頁的內容是通過純粹的 HTML 程式碼來書寫,包括一些資原始檔:圖片、視訊等內容的引入都是使用 HTML 標籤來完成的。
它的好處當然是載入速度快,編寫簡單,訪問的時候對 web 容器基本上不會產生什麼壓力。但是缺點也很明顯,可維護性比較差,不能根據引數動態的顯示內容等等。
有需求就會有發展麼,這時動態網頁就應運而生了。
動態網頁
我們先不說動態網頁的概念,先說說有哪些網站是由動態網頁來構建的。大家常用的某寶、某東、拼夕夕等網站都是由動態網頁組成的。
動態網頁可以解析 URL 中的引數,或者是關聯資料庫中的資料,顯示不同的網頁內容。
現在各位同學訪問的網站大多數都是動態網站,它們不再簡簡單單是由 HTML 堆砌而成,可能是由 JSP 、 PHP 等語言編寫的,當然,現在很多由前端框架編寫而成的網頁小編這裡也歸屬為動態網頁。
說到動態網頁,各位同學可能使用頻率最高的一個功能是登入,像各種電商類網站,肯定是登入了以後才能下單買東西。那麼,問題來了,後面的服務端是如何知道當前這個人已經登入了呢?
HTTP/1.1
現在大多數的網站使用的協議都是 HTTP/1.1 ,而 HTTP/1.1 最大的特點就是無狀態、無連線的。
無狀態就是指 HTTP 協議對於請求的傳送處理是沒有記憶功能的,也就是說每次 HTTP 請求到達服務端,服務端都不知道當前的客戶端(瀏覽器)到底是一個什麼狀態。客戶端向服務端傳送請求後,服務端處理這個請求,然後將內容響應回客戶端,完成一次互動,這個過程是完全相互獨立的,服務端不會記錄前後的狀態變化,也就是缺少狀態記錄。
這就產生了上面的問題,服務端如何知道當前在瀏覽器面前操作的這個人是誰?
其實,在使用者做登入操作的時候,服務端會下發一個類似於 token 憑證的東西返回至客戶端(瀏覽器),有了這個憑證,才能保持登入狀態。
那麼這個憑證是什麼?
這就是本篇文章要解釋的核心內容,Session 和 Cookies 了。
Session 是會話的意思,會話是產生在服務端的,用來儲存當前使用者的會話資訊,而 Cookies 是儲存在客戶端(瀏覽器),有了 Cookie 以後,客戶端(瀏覽器)再次訪問服務端的時候,會將這個 Cookie 帶上,這時,服務端可以通過 Cookie 來識別本次請求到底是誰在訪問。
可以簡單理解為 Cookies 中儲存了登入憑證,我們只要持有這個憑證,就可以在服務端保持一個登入狀態。
在爬蟲中,有時候遇到需要登入才能訪問的網頁,只需要在登入後獲取了 Cookies ,在下次訪問的時候將登入後獲取到的 Cookies 放在請求頭中,這時,服務端就會認為我們的爬蟲是一個正常登入使用者。
Session 保持
那麼,Cookies 是如何保持會話狀態的呢?
在客戶端(瀏覽器)第一次請求服務端的時候,服務端會返回一個請求頭中帶有 Set-Cookie
欄位的響應給客戶端(瀏覽器),用來標記是哪一個使用者,客戶端(瀏覽器)會把這個 Cookies 給儲存起來。
我們來使用工具 PostMan 來訪問下某東的登入頁,看下返回的響應頭:
當我們輸入好使用者名稱和密碼時,客戶端會將這個 Cookies 放在請求頭一起傳送給服務端,這時,服務端就知道是誰在進行登入操作,並且可以判斷這個人輸入的使用者名稱和密碼對不對,如果輸入正確,則在服務端的 Session 記錄一下這個人已經登入成功了,下次再請求的時候這個人就是登入狀態了。
如果客戶端傳給服務端的 Cookies 是無效的,或者這個 Cookies 根本不是由這個服務端下發的,或者這個 Cookies 已經過期了,那麼接下里的請求將不再能訪問需要登入後才能訪問的頁面。
所以, Session 和 Cookies 之間是需要相互配合的,一個在服務端,一個在客戶端。
Cookies
我們還是開啟某東的網站,看下這些 Cookies到底有哪些內容:
具體操作方式還是在 Chrome 中按 F12 開啟開發者工具,選擇 Application 標籤,點開 Cookies 這一欄。
- Name:這個是 Cookie 的名字。一旦建立,該名稱便不可更改。
- Value:這個是 Cookie 的值。
- Domain:這個是可以訪問該 Cookie 的域名。例如,如果設定為 .jd.com ,則所有以 jd.com ,結尾的域名都可以訪問該Cookie。
- Max Age:Cookie 失效的時間,單位為秒,也常和 Expires 一起使用。 Max Age 如果為正數,則在 Max Age 秒之後失效,如果為負數,則關閉瀏覽器時 Cookie 即失效,瀏覽器也不會儲存該 Cookie 。
- Path:Cookie 的使用路徑。如果設定為 /path/ ,則只有路徑為 /path/ 的頁面可以訪問該 Cookie 。如果設定為 / ,則本域名下的所有頁面都可以訪問該 Cookie 。
- Size:Cookie 的大小。
- HTTPOnly:如果此項打勾,那麼通過 JS 指令碼將無法讀取到 Cookie 資訊,這樣能有效的防止 XSS 攻擊,竊取 Cookie 內容,可以增加 Cookie 的安全性。
- Secure:如果此項打勾,那麼這個 Cookie 只能用 HTTPS 協議傳送給伺服器,用 HTTP 協議是不傳送的。
那麼有的網站為什麼這次關閉了,下次開啟的時候還是登入狀態呢?
這就要說到 Cookie 的持久化了,其實也不能說是持久化,就是 Cookie 失效的時間設定的長一點,比如直接設定到 2099 年失效,這樣,在瀏覽器關閉後,這個 Cookie 是會儲存在我們的硬碟中的,下次開啟瀏覽器,會再從我們的硬碟中將這個 Cookie 讀取出來,用來維持使用者的會話狀態。
第二個問題產生了,服務端的會話也會無限的維持下去麼,當然不會,這就要在 Cookie 和 Session 上做文章了, Cookie 中可以使用加密的方式將使用者名稱記錄下來,在下次將 Cookies 讀取出來由請求傳送到服務端後,服務端悄悄的自己建立一個使用者已經登入的會話,這樣我們在客戶端看起來就好像這個登入會話是一直保持的。
理解誤區
當我們關閉瀏覽器的時候會自動銷燬服務端的會話,這個是錯誤的,因為在關閉瀏覽器的時候,瀏覽器並不會額外的通知服務端說,我要關閉了,你把和我的會話銷燬掉吧。
因為服務端的會話是儲存在記憶體中的,雖然一個會話不會很大,但是架不住會話多啊,硬體畢竟是會有限制的,不能無限擴充下去的,所以在服務端設定會話的過期時間就非常有必要。
當然,有沒有方式能讓瀏覽器在關閉的時候同步的關閉服務端的會話,當然是可以的,我們可以通過指令碼語言 JS 來監聽瀏覽器關閉的動作,當瀏覽器觸發關閉動作的時候,由 JS 像服務端發起一個請求來通知服務端銷燬會話。
由於不同的瀏覽器對 JS 事件的實現機制不一致,不一定保證 JS 能監聽到瀏覽器關閉的動作,所以現在常用的方式還是在服務端自己設定會話的過期時間。
參考
https://baike.baidu.com/item/cookie/1