天天看點

Requests:Python HTTP Module學習筆記(二)(轉)

在上一篇日志中對Requests做了一個整體的介紹,接來下再介紹一些進階的用法,主要資料還是翻譯自官網的文檔,如有錯漏,歡迎指正。

參考資料:http://docs.python-requests.org/en/latest/user/advanced/

會話對象(Session Objects)

一個請求傳遞的參數,在另一個請求是無效的,不過會話對象允許跨請求的儲存參數,還可以從會話執行個體中儲存所有請求的cookies資料。

下面介紹一下在Requests中會話對象主要的API。

跨請求的儲存cookies資料:

s = requests.Session()

s.get('http://httpbin.org/cookies/set/sessioncookie/123456789')
r = s.get("http://httpbin.org/cookies")

print r.text
# '{"cookies": {"sessioncookie": "123456789"}}'
      

傳遞到請求方法中任何字典類型的資料都會設定成會話級别的值,方法級别的參數會覆寫會話級别的參數。

删除一個字典類型的參數:

有時,想從會話中删除一個字典的鍵,要做到這一點,隻要設定方法參數中鍵的值為

None

,它就會自動的被删除掉。

請求和響應對象(Request and Response Objects)

每當調用requests.*()的請求方法時,主要做兩個事情,第一個是構造一個請求對象對伺服器發起請求或者查詢一些資源。第二個是在請求從伺服器獲得一個響應時生成一個響應對象。響應對象包含從伺服器傳回的所有資訊也包含最初構造的請求對象。以下這個例子是一個簡單的請求從Wikipedia的伺服器傳回一些重要的資訊:

>>> r = requests.get('http://en.wikipedia.org/wiki/Monty_Python')
      

如果想通路從伺服器傳回給我們的标頭資訊,可以這樣做:

>>> r.headers
{'content-length': '56170', 'x-content-type-options': 'nosniff', 'x-cache':
'HIT from cp1006.eqiad.wmnet, MISS from cp1010.eqiad.wmnet', 'content-encoding':
'gzip', 'age': '3080', 'content-language': 'en', 'vary': 'Accept-Encoding,Cookie',
'server': 'Apache', 'last-modified': 'Wed, 13 Jun 2012 01:33:50 GMT',
'connection': 'close', 'cache-control': 'private, s-maxage=0, max-age=0,
must-revalidate', 'date': 'Thu, 14 Jun 2012 12:59:39 GMT', 'content-type':
'text/html; charset=UTF-8', 'x-cache-lookup': 'HIT from cp1006.eqiad.wmnet:3128,
MISS from cp1010.eqiad.wmnet:80'}
      

然而,如果想通路請求發送給伺服器的标頭資訊:

>>> r.request.headers
{'Accept-Encoding': 'identity, deflate, compress, gzip',
'Accept': '*/*', 'User-Agent': 'python-requests/0.13.1'}
      

SSL證書驗證(SSL Cert Verification)

Requests就像一個web浏覽器一樣,可以驗證SSL證書和HTTPS請求,檢查主機的SSL證書,可以使用

verify

參數:

>>> requests.get('https://kennethreitz.com', verify=True)
requests.exceptions.SSLError: hostname 'kennethreitz.com' doesn't match either of '*.herokuapp.com', 'herokuapp.com'
      

https://kennethreitz.com

這個域名沒有設定SSL證書,是以它驗證失敗了,Github就能通過驗證:

>>> requests.get('https://github.com', verify=True)
<Response [200]>
      

預設情況下

verify

的值為True,

verify

選項隻适用于驗證主機的證書。

還可以指定本地的證書檔案作為一個路徑或鍵值對:

>>> requests.get('https://kennethreitz.com', cert=('/path/server.crt', '/path/key'))
<Response [200]>
      

如果指定一個錯誤的路徑或無效的證書:

>>> requests.get('https://kennethreitz.com', cert='/wrong_path/server.pem')
SSLError: [Errno 336265225] _ssl.c:347: error:140B0009:SSL routines:SSL_CTX_use_PrivateKey_file:PEM lib
      

正文内容的工作流程(Body Content Workflow)

預設情況下,當發出一個請求,響應正文會立即被下載下傳,你可以覆寫這個行為來推遲下載下傳響應正文直到你通過

stream

這個參數來通路Response.content屬性:

tarball_url = 'https://github.com/kennethreitz/requests/tarball/master'
r = requests.get(tarball_url, stream=True)
      

這時候,隻有響應的标頭被下載下傳和連接配接仍然保持打開,是以,我們可以有條件的檢索内容:

if int(r.headers['content-length']) < TOO_LONG:
  content = r.content
  ...
      

通過使用

Response.iter_content

Response.iter_lines

方法你可以進一步的控制工作流程,或者通過

Response.raw

閱讀底層urllib3的urllib3.HTTPResponse.

Keep-Alive

由于使用urllib3,在會話中keep-Alive是100%自動的,在一個會話中建立的任何請求都會自動使用适當的連接配接。

注意,當所有的正文資料已被讀取,連接配接會被釋放回池中以便重用;一定要設定

stream

為False或者讀取響應對象的

content

屬性。

流上傳(Streaming Uploads)

Requests支援流上傳,它允許你發送大量的流或檔案而不讀取到記憶體中,流上傳,隻需要為正文提供一個類似檔案的對象:

with open('massive-body') as f:
    request.post('http://some.url/streamed', data=f)
      

資料塊編碼請求(Chunk-Encoded Requests)

Requets還為傳入和傳出的請求提供塊傳輸編碼的支援,發送一個塊編碼的請求,為你的正文簡單的提供一個生成器(或者任何沒有長度的疊代器):

def gen():
    yield 'hi'
    yield 'there'

request.post('http://some.url/chunked', data=gen())
      

事件鈎子(Event Hooks)

Requests有一個hook系統,你可以用它來操縱部分請求過程,或者進行信号事件的處理。

可用的hooks:

response

響應從一個請求産生。

根據每條請求可以指定一個hook函數通過一個

{hook_name: callback_function}

字典類型的hook請求參數:

hooks=dict(response=print_url)
      

回調函數會收到一個塊資料作為第一個參數。

def print_url(r):
    print(r.url)
      

當執行回調的時候如果出現了錯誤,會給出一個警告。

如果回調函數傳回一個值,就認為它是在傳遞時替換資料的,如果函數沒有傳回任何值,那它就沒有什麼其他的影響。

在運作時輸出一些請求方法的參數:

>>> requests.get('http://httpbin.org', hooks=dict(response=print_url))
http://httpbin.org
<Response [200]>
      

自定義的身份驗證(Custom Authentication)

Requests允許你使用指定的自定義的身份驗證機制。

任何可調用的請求方法通過

auth

參數,在派發之前可以修改請求。

身份驗證很容易定義,都是繼承于

requests.auth.AuthBase

的子類。Requests提供兩種常見的身份驗證方案實作在

requests.auth: HTTPBasicAuth

HTTPDigestAuth

我們假裝我們有一個web服務,它隻會在标頭的

X-Pizza

被設定為一個密碼值時傳回響應,雖然不太可能,但隻是用它就好:

from requests.auth import AuthBase

class PizzaAuth(AuthBase):
    """Attaches HTTP Pizza Authentication to the given Request object."""
    def __init__(self, username):
        # setup any auth-related data here
        self.username = username

    def __call__(self, r):
        # modify and return the request
        r.headers['X-Pizza'] = self.username
        return r
      

然後,我們可以建立一個請求使用Pizza驗證:

>>> requests.get('http://pizzabin.org/admin', auth=PizzaAuth('kenneth'))
<Response [200]>
      

流請求(Streaming Requests)

利用

requests.Response.iter_lines()

方法,你可以輕松的周遊流API如Twitter Streaming API.

使用Twitter Streaming API去跟蹤“requests”關鍵字:

import requests
import json

r = requests.post('https://stream.twitter.com/1/statuses/filter.json',
    data={'track': 'requests'}, auth=('username', 'password'), stream=True)

for line in r.iter_lines():
    if line: # filter out keep-alive new lines
        print json.loads(line)
      

代理(Streaming Requests)

如果你需要使用一個代理,你可以在任何請求方法中使用

proxies

參數配置單個請求:

import requests

proxies = {
  "http": "10.10.1.10:3128",
  "https": "10.10.1.10:1080",
}

requests.get("http://example.org", proxies=proxies)
      

你也可以通過環境變量

HTTP_PROXY

HTTPS_PROXY

來配置代理:

$ export HTTP_PROXY="10.10.1.10:3128"
$ export HTTPS_PROXY="10.10.1.10:1080"
$ python
>>> import requests
>>> requests.get("http://example.org")
      

為你的代理使用HTTP的基本認證,可以使用這樣

http://user:password@host/

的格式:

proxies = {
    "http": "http://user:[email protected]:3128/",
}
      

符合(Compliance)

編碼(Encodings)

超文本傳輸協定(HTTP Verbs)

連結标題(Link Headers)