會話對象
會話對象讓你能夠跨請求保持某些參數。它也會在同一個Session實例發出的所有請求之間保持cookie,期間使用urllib3的connection pooling功能。所以如果你向同一主機發送多個請求,底層的TCP鏈接將會被重用,從而帶來顯著的性能提升。
我們來跨請求保持一些cookie:
會話也可用來為請求方法提供缺省數據。這是通過為會話對象的屬性提供數據來實現的:
任何你傳遞給請求方法的字典都會與已設置會話層數據合並。方法層的參數覆蓋會話的參數。
不過需要注意,就算使用了會話,方法級別的參數也不會被跨請求保持。下面的例子只會和第一個請求發送cookie,而非第二個;
從字典參數中移除一個值:
有時你會想省略字典參數中一些會話層的鍵。要做到這一點,你只需簡單地在方法層參數中將那個鍵的值設置為None,那個鍵就會被自動省略掉。
請求與響應對象
任何時候進行了類似requests.get()的調用,你都在做兩件主要的事情。其一,你在構建一個Request對象,該對象將被發送到某個服務器請求或查詢一些資源。其二。一旦requests得到一個從服務器返回的響應就會產生一個Response對象。該響應對象包含服務器返回的所有信息,也包含你原來創建的request對象。
准備的請求
當你從API或者會話調用中收到一個Response對象時,request屬性其實是使用了PrepareRequest。有時在發送請求之前,你需要對body或者header做一些額外處理。
SSL證書驗證
Requests可以為HTTPS請求驗證SSL證書,就像web瀏覽器一樣。SSL驗證默認是開啟的。
客戶端證書
你也可以指定一個本地證書用作客戶端證書,可以是單個文件(包含密鑰和證書)或一個包含兩個文件路徑的元組:
CA證書
Requests默認附帶了一套它信任的根證書,來自於Mozilla trust store。
響應體內容工作流
默認情況下,當你進行網絡請求后,響應體會立即被下載。你可以通過stream參數覆蓋這個行為,推遲下載響應體直接訪問Response.content屬性。
import requests #s=requests.get("https://www.baidu.com") s=requests.get("https://www.baidu.com",stream=True) print(s.content)
如果你在請求中把 stream
設為 True
,Requests 無法將連接釋放回連接池,除非你 消耗了所有的數據,或者調用了 Response.close
。 這樣會帶來連接效率低下的問題。如果你發現你在使用 stream=True
的同時還在部分讀取請求的 body(或者完全沒有讀取 body),那么你就應該考慮使用 with 語句發送請求,這樣可以保證請求一定會被關閉:
with requests.get('http://httpbin.org/get', stream=True) as r: # 在此處理響應。
保持活動狀態(持久連接)
好消息——歸功於 urllib3,同一會話內的持久連接是完全自動處理的!同一會話內你發出的任何請求都會自動復用恰當的連接!
注意:只有所有的響應體數據被讀取完畢連接才會被釋放為連接池;所以確保將 stream
設置為 False
或讀取 Response
對象的 content
屬性。
流式上傳
Requests支持流式上傳,這允許你發送大的數據流或文件而無需先把它們讀入內存。
要使用流式上傳,僅需為你的請求體提供一個類文件對象即可:
塊編碼請求
對於出去或進來的請求,Requsts也支持分塊傳輸編碼。要發送一個塊編碼的請求,僅需為你的請求體提供一個生成器(或任意沒有具體長度的迭代器):
POST多個分塊編碼的文件
你可以在一個請求中發送多個文件。
事件掛鈎
Requests有一個鈎子系統,你可以用來操控部分請求過程,或信號事件處理。
自定義身份驗證
Requests允許你使用自己指定的身份驗證機制。
任何傳遞給請求方法的auth參數的可調用對象,在請求發出之前都有機會修改請求。
自定義的身份驗證機制是作為requests.auth.AuthBase的子類來實現的,也非常容易定義。Requests在requests.auth中提供了兩種常見的身份驗證方案:
HTTPBasicAuth和HTTPDigestAuth。
流式請求
使用Response.iter_lines()你可以很方便地對流式API進行迭代。簡單地設置stream為True便可以使用iter_lines對響應進行迭代:
import json import requests r = requests.get('http://httpbin.org/stream/20', stream=True) for line in r.iter_lines(): # filter out keep-alive new lines if line: decoded_line = line.decode('utf-8') print(json.loads(decoded_line))
代理
如果需要使用代理,你可以通過為任意請求方法提供proxies參數來配置單個請求:
SOCKS
除了基本的HTTP代理,Request還支持SOCKS協議的代理。這是一個可選功能,若要使用,你需要安裝第三方庫。
合規性
Requests符合所有相關的規范和RFC,這樣不會為用戶造成不必要的困難。但這種對規范的考慮導致一些行為對於不熟悉相關規范的人來說看似有點奇怪。
編碼方式
HTTP動詞
Requests提供了幾乎所有HTTP動詞的功能:GET,OPTIONS,HEAD,POST,PUT,PATCH,DELETE。以下內容為使用Requests中的這些動詞以及Github API提供了詳細示例。
定制動詞
有時候你會碰到一些服務器,處於某些原因,他們允許或者要求用戶使用上述HTTP動詞之外的定制動詞。比如說WEBDAV服務器會要求你使用MKCOL方法。別擔心,Requests一樣可以搞定他們。你可以使用內建的.requests方法;
響應頭鏈接字段
許多HTTP API都有響應頭鏈接字段的特性,他們使得API能夠更好地自我描述和自我暴露。
傳輸適配器
從v1.0.0以后,Requests的內部采用了模塊化設計。部分原因是為了實現傳輸適配器。
阻塞和非阻塞
使用默認的傳輸適配器,Requests不提供任何形式的非阻塞IO。Response.content屬性會阻塞,直到整個響應下載完成。
Header排序
在某些特殊情況下你也許需要按照次序來提供header,如果你向headers關鍵字參數傳入一個OrderDict,就可以向提供一個帶排序的header。然而,Requests 使用的默認 header 的次序會被優先選擇,這意味着如果你在 headers
關鍵字參數中覆蓋了默認 header,和鍵字參數中別的 header 相比,它們也許看上去會是次序錯誤的。
如果這個對你來說是個問題,那么用戶應該考慮在 Session
對象上面設置默認 header,只要將 Session
設為一個定制的 OrderedDict
即可。這樣就會讓它成為優選的次序。
超時(timeout)
為防止服務器不能及時響應,大部分發至外部服務器的請求都應該帶着timeout參數。在默認情況下,除非顯式指定了timeout值,requests是不會自動進行超時處理的。如果沒有timeout,你的代碼可能會掛起若干分鍾甚至更長時間。
連接超時指的是在你的客戶端實現到遠端機器端口的連接時(對應的是`connect()`_),Request 會等待的秒數。一個很好的實踐方法是把連接超時設為比 3 的倍數略大的一個數值,因為 TCP 數據包重傳窗口 (TCP packet retransmission window) 的默認大小是 3。
一旦你的客戶端連接到了服務器並且發送了 HTTP 請求,讀取超時指的就是客戶端等待服務器發送請求的時間。(特定地,它指的是客戶端要等待服務器發送字節之間的時間。在 99.9% 的情況下這指的是服務器發送第一個字節之前的時間)。