我們都知道 HTTP 是無狀態(tài)的赤兴,用戶每次打開 web 頁面時横漏,服務(wù)器都打開新的會話抠艾,而且服務(wù)器也不會自動維護客戶的上下文信息纫塌,那么服務(wù)器是怎么識別用戶的呢诊县?
這就是本文的主要內(nèi)容,當服務(wù)端需要記錄用戶的狀態(tài)時措左,就需要用某種機制來識具體的用戶依痊,這個機制就是 session 和 cookie
Session 和 Cookie
session 是保存在服務(wù)器端的,用于標識用戶怎披,并且跟蹤用戶的一種上下文保持機制胸嘁。當服務(wù)器創(chuàng)建了一個 Session 時瓶摆,給客戶端發(fā)送的響應(yīng)報文包含了 Set-Cookie 字段,其中有一個名為 sid 的鍵值對性宏,這個鍵值對就是 Session ID赏壹。客戶端收到后就把 Cookie 保存在瀏覽器中衔沼,并且之后發(fā)送的請求報文都包含 Session ID
Cookie 由服務(wù)器生成蝌借,發(fā)送給瀏覽器,瀏覽器把 Cookie 以 kv 形式保存到某個目錄下的文本文件內(nèi)指蚁。是客戶端保存用戶信息的一種機制菩佑,用來記錄用戶的一些信息,它是實現(xiàn) Session 的一種方式凝化。
瀏覽器會根據(jù)響應(yīng)報文里的一個叫做 Set-Cookie 的首部字段信息稍坯,將其保存在本地。
當下一次請求時會把該 Cookie 發(fā)送給服務(wù)器搓劫,之后服務(wù)端發(fā)現(xiàn)客戶端發(fā)送過來的 Cookie 后瞧哟,會檢查是那個客戶端發(fā)送過來的請求,然后對服務(wù)器上的記錄枪向,最后得到了之前的狀態(tài)信息勤揩。
我們經(jīng)常看到登錄的時候秘蛔,有個下次自動登錄的選項陨亡,就是根據(jù)這個原理來實現(xiàn)的。
既然瀏覽器能實現(xiàn)免密登錄的功能深员,那么我們用代碼如何來實現(xiàn)呢?
這里有兩個登錄案例负蠕,看完之后你就知道如何實現(xiàn)了。
案例一:豆瓣登錄
在這里我們使用 Python 中的 LWPCookieJar 倦畅,它是管理 cookie 的工具遮糖,可以將 cookie 保存到文件,在文件中讀取本地 cookie 數(shù)據(jù)到程序中叠赐,一般用到以下兩種方法:
- 將登錄成功的 cookie 寫入到本地文件
# 實例化一個 LWPCookieJar 對象欲账,并設(shè)置保存 cookie 的文件
session = requests.session()
session.cookies = LWPCookieJar(filename='DouBanCookies.txt')
在使用代碼登錄成功之后,使用 session.save() 將自動將 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
寫入之后燎悍,會在當前目錄生成 DouBanCookies.txt 的文件敬惦,如下圖所示:
- 直接使用該文件中的 cookie 實現(xiàn)免密碼登錄
直接使用 load 方法,從文件中獲取 cookie 到代碼中谈山。其中 load 方法有兩個可選值俄删,ignore_discard 主要是忽略關(guān)閉瀏覽器丟失, ignore_expires 是忽略 cookie 失效〕胍可根據(jù)自己的實際場景自由選擇臊诊。
session.cookies.load(ignore_discard=True)
使用 cookie 登錄之后,可以自主驗證一下是否登錄成功斜脂。一般選擇訪問個人主頁抓艳,查看響應(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') # 實例化一個LWPCookieJar對象
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 中偏友。
例如,新榜的登錄对供,通過我的測試發(fā)現(xiàn)位他,主要是校驗 token 和用戶名這兩個參數(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 登錄后窿冯,可以選擇訪問登錄之后才能訪問的地址進行驗證,具體代碼就不貼了醋粟,邏輯和上面的案例差不多靡菇,只是處理方法不一樣。
總結(jié)
本文主要是介紹 session 和 cookie 的一些基本概念米愿,以及兩者之間的區(qū)別。同時給大伙介紹了兩種用代碼處理 cookie 的案例鼻吮,這里要注意一下 cookie 存在時效性育苟,如果失效了需要重新用密碼登錄。感興趣的朋友可以根據(jù)以上兩個案例去練練手噢椎木。如果覺得本文不錯违柏,請幫忙點個贊唄~~
公眾號: Python編程與實戰(zhàn)