1. 程式人生 > 實用技巧 >requests學習筆記01

requests學習筆記01

一、傳送請示

# 匯入 Requests 模組
import requests
# 獲取某個網頁
r = requests.get("http://www.baidu.com")

  可以傳送 HTTP POST、PUT、DELETE、HEAD 以及 OPTIONS 請求:

r = requests.post('http://httpbin.org/post', data = {'key':'value'})
r = requests.put('http://httpbin.org/put', data = {'key':'value'})
r = requests.delete('http://httpbin.org/delete
') r = requests.head('http://httpbin.org/get') r = requests.options('http://httpbin.org/get')

二、傳遞 URL 引數

  比如http://httpbin.org/get?key=val傳遞key=val的引數, 在Request 使用 params 關鍵字引數,以一個字串字典來提供這些引數。舉例,如想傳遞 key1=value1 和 key2=value2 到http://httpbin.org/get ,可以使用如下程式碼

payload = {'key1':'value1', 'key2':'value2'}
r 
= requests.get("http://httpbin.org/get", params=payload) # 檢視列印 URL 地址是否正確 print(r.url) # out: http://httpbin.org/get?key2=value2&key1=value1

  注意:字典裡值為 None 的鍵不會被新增到 URL 的查詢字串裡。

  還可以將一個列表作為值傳入,例如下:

payload = {'key1': 'value1', 'key2': ['value2', 'value3']}
r = requests.get(('http://httpbin.org/get', params=payload)
print(r.url) # out: http://httpbin.org/get?key1=value1&key2=value2&key2=value3

三、響應內容

  讀取伺服器響應的內容。例如下:

# 匯入 Requests 模組
import requests
# 獲取某個網頁
r = requests.get("https://api.github.com/events")
# 獲取伺服器響應內容
print(r.text)

# out: 
u'[{"repository":{"open_issues":0,"url":"https://github.com/...

  使用 r.encoding = "ISO-8859-1" 修改文字編碼格式,顯示改變編碼後的響應內容。如果你想在使用特殊邏輯計算出文字的編碼的情況下來修改編碼,應該使用 r.content 來找到編碼,然後設定 r.conding 為相應的編碼。這樣就能使用正確的編碼解析 r.text 了。在學習codecs模組後,可以使用定製的編碼。

四、二進位制響應內容

  你能以位元組的方式訪問請求響應體,對於非文字請求:

>>> c.content
b'[{"repository":{"open_issues":0,"url":"https://github.com/...

  Requests 會自動為你解碼 gzip 和 deflate 傳輸編碼的響應資料。

  例如,以請求返回的二進位制資料建立一張圖片,你可以使用如下程式碼:

>>> from PIL import Image
>>> from io import BytesIO
>>> i = Image.open(BytesIO(r.content))

四、JSON響應內容

  Requests 中也有一個內建的 JSON 解碼器,助力處理 JSON 資料:

>>> import requests
>>> r = requests.get('https://api.github.com/events')
>>> r.json()
[{u'repository': {u'open_issues': 0, u'url': 'https://github.com/...

  如果JSON解碼失敗, r.json() 就會丟擲一個異常。例如,響應內容是401 (Unauthorized),嘗試訪問 r.json() 將會丟擲 ValueError: No JSON object could be decoded 異常。

  注意點,成功呼叫 r.json() 並不意味著響應的成功。有的伺服器會在失敗的響應中包含一個JSON物件(比如HTTP 500的錯誤細節)。這種 JSON 會被解碼返回。要檢查請求是否成功,請使用 r.raise_for_status() 或者檢查r.status_code 是否和你的期望相同。

五、原始響應內容

  在罕見的情況下,你可能想獲取來自伺服器的原始套接字響應,那麼你可以訪問 r.raw。如果你確定想這麼幹,那請你確保在初始請求中設定了 stream=True。具體你可以這麼做:

>>> r = requests.get('https://api.github.com/events', stream=True)
>>> r.raw
<requests.packages.urllib3.response.HTTPResponse object at 0x101194810>
>>> r.raw.read(10)
'\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\x03'

  但一般情況下,你應該以下面的模式將文字流儲存到檔案中:

with open(filename, 'wb') as fd:
    for chunk in r.iter_content(chunk_size):
        fd.write(chunk)

使用 Response.iter_content 將會處理大量你直接使用 Response.raw 不得不處理的。當流下載時,上面是優先推薦的獲取內容方式。

六、定製請求頭

  如果你想為請求新增 HTTP 頭部,只要簡單地傳遞一個 dict 給 headers 引數就可以了。例如,在前一個示例中我們沒有指定 content-type:

>>> url = 'https://api.github.com/some/endpoint'
>>> headers = {'user-agent': 'my-app/0.0.1'}
>>> r = requests.get(url, headers=headers)

  注意:定製 header 的優先順序低於某些特定的資訊源,例如:

  • 如果在.netrc中設定了使用者認證資訊,使用headers=設定的授權就不會生效。而如果設定了auth=引數,``.netrc`` 的設定就無效了。
  • 如果被重定向到別的主機,授權 header 就會被刪除。
  • 代理授權 header 會被 URL 中提供的代理身份覆蓋掉。
  • 在我們能判斷內容長度的情況下,header 的 Content-Length 會被改寫。

  更進一步講,Requests不會基於定製 header 的具體情況改變自己的行為。只不過在最後的請求中,所有的header 資訊都會被傳遞進去。

  注意: 所有的 header 值必須是string、bytestring 或者 unicode。儘管傳遞 unicode header 也是允許的,但不建議這樣做。

七、更加複雜的POST請求

  通常,你想要傳送一些編碼為表單形式的資料——非常像一個 HTML 表單。要實現這個,只需簡單地傳遞一個字典給 data 引數。你的資料字典在發出請求時會自動編碼為表單形式:

>>> payload = {'key1': 'value1', 'key2': 'value2'}
>>> r = requests.post("http://httpbin.org/post", data=payload)
>>> print(r.text)
{
  ...
  "form": {
    "key2": "value2",
    "key1": "value1"
  },
  ...
}

  你還可以為 data 引數傳入一個元組列表。在表單中多個元素使用同一 key 的使用,這種方式 尤其有效:

>>> payload = (('key1', 'value1'), ('key1', 'value2'))
>>> r = requests.post('http://httpbin.org/post', data=payload)
>>> print(r.text)
{
  ...
  "form": {
    "key1": [
      "value1",
      "value2"
    ]
  },
  ...
}

  很多時候你想要傳送的資料並非編碼為表單形式的。如果你傳遞一個string而不是一個dict,那麼資料會被直接釋出出去。例如,Github API v3 接受編碼為 JSON 的 POST/PATCH 資料:

>>> import json

>>> url = 'https://api.github.com/some/endpoint'
>>> payload = {'some': 'data'}

>>> r = requests.post(url, data=json.dumps(payload))

  此處除了可以自行對dict進行編碼,你還可以使用json引數直接傳遞,然後它就會被自動編碼。這是 2.4.2 版的新加功能:

>> url = 'https://api.github.com/some/endpoint'
>>> payload = {'some': 'data'}

>>> r = requests.post(url, json=payload)