1. Cookie 介紹 HTTP 協議是無狀態的。因此,若不藉助其他手段,遠程的伺服器就無法知道以前和客戶端做了哪些通信。Cookie 就是「其他手段」之一。 Cookie 一個典型的應用場景,就是用於記錄用戶在網站上的登錄狀態。 用戶登錄成功後,伺服器下發一個(通常是加密了的)Cookie 文件 ...
1. Cookie 介紹
HTTP 協議是無狀態的。因此,若不藉助其他手段,遠程的伺服器就無法知道以前和客戶端做了哪些通信。Cookie 就是「其他手段」之一。 Cookie 一個典型的應用場景,就是用於記錄用戶在網站上的登錄狀態。
- 用戶登錄成功後,伺服器下發一個(通常是加密了的)Cookie 文件。
- 客戶端(通常是網頁瀏覽器)將收到的 Cookie 文件保存起來。
- 下次客戶端與伺服器連接時,將 Cookie 文件發送給伺服器,由伺服器校驗其含義,恢復登錄狀態(從而避免再次登錄)。
2. requests使用cookie
當瀏覽器作為客戶端與遠端伺服器連接時,遠端伺服器會根據需要,產生一個 SessionID,並附在 Cookie 中發給瀏覽器。接下來的時間里,只要 Cookie 不過期,瀏覽器與遠端伺服器的連接,都會使用這個 SessionID;而瀏覽器會自動與伺服器協作,維護相應的 Cookie。
在 requests
中,也是這樣。我們可以創建一個 requests.Session
,爾後在該 Session 中與遠端伺服器通信,其中產生的 Cookie, requests
會自動為我們維護好。
3. POST 表單
post 方法可以將一組用戶數據,以表單的形式發送到遠端伺服器。遠端伺服器接受後,依照表單內容做相應的動作。
調用 requests
的 POST 方法時,可以用 data
參數接收一個 Python 字典結構。 requests
會自動將 Python 字典序列化為實際的表單內容。例如:
import requests cs_url = 'http://httpbin.org/post' my_data = { 'key1' : 'value1', 'key2' : 'value2' } r = requests.post (cs_url, data = my_data) print r.content
4. 實際模擬登錄 GitHub 試試看
模擬登錄的第一步,首先是要搞清楚我們用瀏覽器登錄時都發生了什麼。
GitHub 登錄頁面是 https://github.com/login 。我們首先清空瀏覽器 Cookie 記錄,然後用 Chrome 打開登錄頁面。填入 Username 和 Password 之後,我們打開 Tamper Chrome 和 Chrome 的元素審查工具(找到 Network 標簽頁),之後點登錄按鈕。
在 Tamper Chrome 中,我們發現:雖然登錄頁面是 https://github.com/login ,但實際接收表單的是 https://github.com/session 。若登錄成功,則跳轉到 https://github.com/ 首頁,返回狀態碼 200
。
而在 Chrome 的審查元素視窗中,我們可以看到提交給 session
介面的表單信息。內里包含
commit utf8 authenticity_token login password
其中, commit
和 utf8
兩項是定值; login
和 password
分別是用戶名和密碼,這很好理解。唯獨 authenticity_token
是一長串無規律的字元,我們不清楚它是什麼。
POST 動作發生在與 session
介面交互之前,因此可能的信息來源只有 login
介面。我們打開 login 頁面的源碼,試著搜索 authenticity_token
就不難發現有如下內容:
<input name="authenticity_token" type="hidden" value="......" />
原來,所謂的 authenticity_token
是明白寫在 HTML 頁面里的,只不過用 hidden
模式隱藏起來了。為此,我們只需要使用 Python 的正則庫解析一下,就好了。
import requests import re login_url = 'https://github.com/login' user = 'user' //具體賬號 password = 'password' //具體密碼 user_headers = { 'User-Agent' : 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/48.0.2564.116 Safari/537.36', 'Accept' : 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8', 'Accept-Encoding' : 'gzip', 'Accept-Language' : 'zh-CN,zh;q=0.8,en;q=0.6,zh-TW;q=0.4' } session = requests.Session() response = session.get(login_url, headers = user_headers) pattern = re.compile(r'<input name="authenticity_token" type="hidden" value="(.*)" />') authenticity_token = pattern.findall(response.content)[0] login_data = { 'commit' : 'Sign in', 'utf8' : '%E2%9C%93', 'authenticity_token' : authenticity_token,'login' : user, 'password' : password } session_url = 'https://github.com/session' response = session.post(session_url, headers = user_headers, data = login_data)
1. 首先,我們準備好了和 Chrome 一致的 HTTP 請求頭部信息。具體來說,其中的 User-Agent
是比較重要的。
2. 仿照瀏覽器與伺服器的通信,我們創建了一個 requests.Session
。
3. 我們用 GET 方法打開登錄頁面,並用正則庫解析到 authenticity_token
。
4. 將所需的數據,整備成一個 Python 字典login_data
5. 最後,用 POST 方法,將表單提交到 session
介面。
6. 最終的結果經由 302
跳轉,打開了( 200
)GitHub 首頁.