我們都知道 HTTP 是無(wú)狀態(tài)的,用戶每次打開 web 頁(yè)面時(shí),服務(wù)器都打開新的會(huì)話,而且服務(wù)器也不會(huì)自動(dòng)維護(hù)客戶的上下文信息,那么服務(wù)器是怎么識(shí)別用戶的呢?
這就是本文今天要講解的內(nèi)容。當(dāng)服務(wù)端需要記錄用戶的狀態(tài)時(shí),就需要用某種機(jī)制來識(shí)具體的用戶,這個(gè)機(jī)制就是 session 和 cookie。
轉(zhuǎn)載來源:公眾號(hào):Python 編程與實(shí)戰(zhàn)
“ 閱讀本文大概需要 9 分鐘。”
Session 和 Cookie
session 是保存在服務(wù)器端的,用于標(biāo)識(shí)用戶,并且跟蹤用戶的一種上下文保持機(jī)制。當(dāng)服務(wù)器創(chuàng)建了一個(gè) Session 時(shí),給客戶端發(fā)送的響應(yīng)報(bào)文包含了 Set-Cookie 字段,其中有一個(gè)名為 sid 的鍵值對(duì),這個(gè)鍵值對(duì)就是 Session ID。客戶端收到后就把 Cookie 保存在瀏覽器中,并且之后發(fā)送的請(qǐng)求報(bào)文都包含 Session ID
Cookie 由服務(wù)器生成,發(fā)送給瀏覽器,瀏覽器把 Cookie 以 kv 形式保存到某個(gè)目錄下的文本文件內(nèi)。是客戶端保存用戶信息的一種機(jī)制,用來記錄用戶的一些信息,它是實(shí)現(xiàn) Session 的一種方式。
瀏覽器會(huì)根據(jù)響應(yīng)報(bào)文里的一個(gè)叫做 Set-Cookie 的首部字段信息,將其保存在本地。
當(dāng)下一次請(qǐng)求時(shí)會(huì)把該 Cookie 發(fā)送給服務(wù)器,之后服務(wù)端發(fā)現(xiàn)客戶端發(fā)送過來的 Cookie 后,會(huì)檢查是那個(gè)客戶端發(fā)送過來的請(qǐng)求,然后根據(jù)服務(wù)器上的記錄,最后得到了之前的狀態(tài)信息。
我們經(jīng)常看到登錄的時(shí)候,有個(gè)下次自動(dòng)登錄的選項(xiàng),就是根據(jù)這個(gè)原理來實(shí)現(xiàn)的。既然瀏覽器能實(shí)現(xiàn)免密登錄的功能,那么我們用代碼如何來實(shí)現(xiàn)呢?
這里有兩個(gè)登錄案例,看完之后你就知道如何實(shí)現(xiàn)了。
案例一:豆瓣登錄
在這里我們使用 Python 中的 LWPCookieJar ,它是管理 cookie 的工具,可以將 cookie 保存到文件,在文件中讀取本地 cookie 數(shù)據(jù)到程序中,一般用到以下兩種方法:
源碼
1. 將登錄成功的 cookie 寫入到本地文件
# 實(shí)例化一個(gè) LWPCookieJar 對(duì)象,并設(shè)置保存 cookie 的文件 session = requests.session() session.cookies = LWPCookieJar(filename='DouBanCookies.txt')
在使用代碼登錄成功之后,使用 session.save() 將自動(dòng)將 cookie 寫入到設(shè)置的 cookie 文件中
def login(): name = input("輸入賬戶:") password = input("輸入密碼:") url = "https://accounts.douban.com/j/mobile/login/basic" data = { "ck": "", "name": name, "password": password, "remember": "True", "ticket": "", } response = session.post(url, data=data) print(response.text) session.cookies.save() # 保存 cookie
寫入之后,會(huì)在當(dāng)前目錄生成 DouBanCookies.txt 的文件,如下圖所示:
2. 直接使用該文件中的 cookie 實(shí)現(xiàn)免密登錄
直接使用 load 方法,從文件中獲取 cookie 到代碼中。其中 load 方法有兩個(gè)可選值,ignore_discard 主要是忽略關(guān)閉瀏覽器丟失, ignore_expires 是忽略 cookie 失效。可根據(jù)自己的實(shí)際場(chǎng)景自由選擇。
session.cookies.load(ignore_discard=True)
使用 cookie 登錄之后,可以自主驗(yàn)證一下是否登錄成功。一般選擇訪問個(gè)人主頁(yè),查看響應(yīng)內(nèi)容,判讀是否登錄成功。完整代碼如下:
# coding: utf-8 import requests from scrapy import Selector from http.cookiejar import LWPCookieJar session = requests.session() headers = { "User-Agent": "Mozilla/5.0 (windows NT 6.1; Win64; x64) AppleWebKit/537.36 (Khtml, like Gecko) Chrome/75.0.3770.100 Safari/537.36" } session.headers = headers session.cookies = LWPCookieJar(filename='DouBanCookies.txt') # 實(shí)例化一個(gè)LWPCookieJar對(duì)象 def login(): name = input("輸入賬戶:") password = input("輸入密碼:") url = "https://accounts.douban.com/j/mobile/login/basic" data = { "ck": "", "name": name, "password": password, "remember": "True", "ticket": "", } response = session.post(url, data=data) print(response.text) session.cookies.save() verify_login() def verify_login(): mine_url = "https://www.douban.com/mine/" mine_response = session.get(mine_url) selector = Selector(text=mine_response.text) user_name = selector.css(".info h1 ::text").extract_first("") print(f"豆瓣用戶名:{user_name.strip()}") def cookie_login(): try: # 從文件中加載cookies(LWP格式) session.cookies.load(ignore_discard=True) print(session.cookies) except Exception: print("Cookies未能加載,使用密碼登錄") login() else: verify_login() if __name__ == "__main__": cookie_login()
案例二:新榜登錄
除了使用 Python 中自帶的 cookie 管理工具之外,我們還可以自己創(chuàng)建 cookie 文件,寫入到本地文件或者 redis 中。
例如,新榜的登錄,通過我的測(cè)試發(fā)現(xiàn),主要是校驗(yàn) token 和用戶名這兩個(gè)參數(shù)。而 token 在登錄成功后,可以在響應(yīng)內(nèi)容中找到。那么我們就可以自己創(chuàng)建 cookie 文件,一般是 .txt 或者.json 文件。
cookies = { "name": self.account, "token": token, "useLoginAccount": "true" }with open("XinBangCookies.txt", 'w')as f: # 將cookies保存到本地 f.write(str(cookies))
然后讀取 cookie 加載到代碼中
with open("XinBangCookies.txt", "r")as f: cookies = f.read() cookies = eval(cookies) cookie = "; ".join((key + "=" + value) for key, value in cookies.items()) self.session.headers.update({"Cookie": cookie})
使用本地 cookie 登錄后,可以選擇訪問登錄之后才能訪問的地址進(jìn)行驗(yàn)證,具體代碼就不貼了,邏輯和上面的案例差不多,只是處理方法不一樣。
總結(jié)
本文主要是介紹 session 和 cookie 的一些基本概念,以及兩者之間的區(qū)別。同時(shí)給大伙介紹了兩種用代碼處理 cookie 的案例,這里要注意一下 cookie 存在時(shí)效性,如果失效了需要重新用密碼登錄。感興趣的朋友可以根據(jù)以上兩個(gè)案例去練練手噢。