快速啟動?

渴望開始?本頁介紹如何開始處理請求。

首先,確保:

讓我們從一些簡單的例子開始。

提出請求?

通過請求發出請求非常簡單。

首先導入請求模塊::

>>> import requests

現在,讓我們嘗試獲取一個網頁。對于這個例子,讓我們獲取Github的公共時間線:

>>> r = requests.get('https://api.github.com/events')

現在,我們有一個 Response 對象調用 r . 我們可以從這個對象中獲得我們需要的所有信息。

請求的簡單API意味著所有形式的HTTP請求都是顯而易見的。例如,這是您發出HTTP POST請求的方式:

>>> r = requests.post('https://httpbin.org/post', data = {'key':'value'})

很好,對吧?其他HTTP請求類型是什么:Put、Delete、Head和Options?這些都很簡單:

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

這一切都很好,但這也只是請求可以做什么的開始。

在URL中傳遞參數?

You often want to send some sort of data in the URL's query string. 如果您是手工構造URL,那么這些數據將在URL中問號后作為鍵/值對給出,例如。 httpbin.org/get?key=val . 請求允許您使用 params 關鍵字參數。舉個例子,如果你想通過 key1=value1key2=value2httpbin.org/get ,您將使用以下代碼::

>>> payload = {'key1': 'value1', 'key2': 'value2'}
>>> r = requests.get('https://httpbin.org/get', params=payload)

您可以通過打印URL看到該URL已正確編碼::

>>> print(r.url)
https://httpbin.org/get?key2=value2&key1=value1

注意任何值為 None 不會添加到URL的查詢字符串中。

還可以將項列表作為值傳遞:

>>> payload = {'key1': 'value1', 'key2': ['value2', 'value3']}

>>> r = requests.get('https://httpbin.org/get', params=payload)
>>> print(r.url)
https://httpbin.org/get?key1=value1&key2=value2&key2=value3

響應內容?

我們可以讀取服務器響應的內容。再次考慮Github時間表:

>>> import requests

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

請求將自動從服務器解碼內容。大多數Unicode字符集是無縫解碼的。

當您發出請求時,請求根據HTTP頭對響應的編碼進行有根據的猜測。訪問時使用請求猜測的文本編碼 r.text . 您可以找到正在使用的編碼請求,并使用 r.encoding 屬性:

>>> r.encoding
'utf-8'
>>> r.encoding = 'ISO-8859-1'

如果更改編碼,請求將使用 r.encoding 無論你什么時候調用 r.text . 您可能希望在任何情況下都這樣做,在這種情況下,您可以應用特殊的邏輯來計算出內容的編碼是什么。例如,HTML和XML能夠在其主體中指定其編碼。在這種情況下,您應該使用 r.content 找到編碼,然后設置 r.encoding . 這會讓你用 r.text 使用正確的編碼。

請求還將在需要時使用自定義編碼。如果您創建了自己的編碼并在 codecs 模塊中,只需使用編解碼器名稱作為 r.encoding 請求將為您處理解碼。

二進制響應內容?

對于非文本請求,您還可以字節形式訪問響應正文:

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

這個 gzipdeflate 傳輸編碼會自動為您解碼。

例如,要從請求返回的二進制數據創建圖像,可以使用以下代碼:

>>> from PIL import Image
>>> from io import BytesIO

>>> i = Image.open(BytesIO(r.content))

JSON響應內容?

還有一個內置的JSON解碼器,以防處理JSON數據:

>>> import requests

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

如果JSON解碼失敗, r.json() 引發異常。例如,如果響應得到204(沒有內容),或者如果響應包含無效的JSON,則嘗試 r.json() 加薪 ValueError: No JSON object could be decoded .

應該注意的是,呼叫成功 r.json()not 表示響應成功。有些服務器可能會在失敗的響應中返回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
<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=128):
        fd.write(chunk)

使用 Response.iter_content 會處理很多你在使用時必須處理的事情 Response.raw 直接。當對下載進行流式處理時,以上是檢索內容的首選和推薦方法。注意 chunk_size 可以自由地調整到一個更適合您的用例的數字。

注解

關于使用 Response.iter_content 對戰 Response.raw . Response.iter_content 將自動解碼 gzipdeflate 傳輸編碼。 Response.raw 是一個原始字節流——它不轉換響應內容。如果在返回字節時確實需要訪問這些字節,請使用 Response.raw .

自定義標題?

如果要向請求添加HTTP頭,只需傳入 dictheaders 參數。

例如,在前面的示例中,我們沒有指定用戶代理:

>>> url = 'https://api.github.com/some/endpoint'
>>> headers = {'user-agent': 'my-app/0.0.1'}

>>> r = requests.get(url, headers=headers)

注意:與更具體的信息源相比,自定義頭的優先級更低。例如:

  • 授權頭設置為 headers= 中指定憑據,則將被重寫 .netrc ,而該屬性又將被 auth= 參數。請求將在以下位置搜索netrc文件 ~/.netrc , ~/_netrc ,或位于 NETRC 環境變量。

  • 如果從主機上重定向,將刪除授權頭。

  • 代理授權頭將被URL中提供的代理憑據覆蓋。

  • 當我們可以確定內容的長度時,內容長度標題將被重寫。

此外,請求根本不會根據指定的自定義頭更改其行為。這些頭只是簡單地傳遞到最終請求中。

注意:所有標題值必須是 string ,bytestring或unicode。在允許的情況下,建議避免傳遞unicode頭值。

更復雜的POST請求?

通常,您希望發送一些表單編碼的數據——很像HTML表單。為此,只需將字典傳遞給 data 參數。發出請求時,您的數據字典將自動進行格式編碼::

>>> payload = {'key1': 'value1', 'key2': 'value2'}

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

這個 data 參數也可以為每個鍵具有多個值。這可以通過 data 以列表為值的元組列表或字典。當表單中有多個元素使用同一個鍵時,這尤其有用:

>>> payload_tuples = [('key1', 'value1'), ('key1', 'value2')]
>>> r1 = requests.post('https://httpbin.org/post', data=payload_tuples)
>>> payload_dict = {'key1': ['value1', 'value2']}
>>> r2 = requests.post('https://httpbin.org/post', data=payload_dict)
>>> print(r1.text)
{
  ...
  "form": {
    "key1": [
      "value1",
      "value2"
    ]
  },
  ...
}
>>> r1.text == r2.text
True

有時您可能希望發送非表單編碼的數據。如果你通過 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)

注意, json 參數被忽略,如果 datafiles 通過。

使用 json 請求中的參數將更改 Content-Type 在標題中 application/json .

發布多部分編碼文件?

請求使上載多部分編碼文件變得簡單:

>>> url = 'https://httpbin.org/post'
>>> files = {'file': open('report.xls', 'rb')}

>>> r = requests.post(url, files=files)
>>> r.text
{
  ...
  "files": {
    "file": "<censored...binary...data>"
  },
  ...
}

可以顯式設置文件名、內容類型和頭:

>>> url = 'https://httpbin.org/post'
>>> files = {'file': ('report.xls', open('report.xls', 'rb'), 'application/vnd.ms-excel', {'Expires': '0'})}

>>> r = requests.post(url, files=files)
>>> r.text
{
  ...
  "files": {
    "file": "<censored...binary...data>"
  },
  ...
}

如果需要,可以發送字符串作為文件接收:

>>> url = 'https://httpbin.org/post'
>>> files = {'file': ('report.csv', 'some,data,to,send\nanother,row,to,send\n')}

>>> r = requests.post(url, files=files)
>>> r.text
{
  ...
  "files": {
    "file": "some,data,to,send\\nanother,row,to,send\\n"
  },
  ...
}

如果您將一個非常大的文件作為 multipart/form-data 請求,您可能需要傳輸請求。默認情況下, requests 不支持,但有一個單獨的包- requests-toolbelt . 你應該閱讀 the toolbelt's documentation 有關如何使用它的詳細信息。

要在一個請求中發送多個文件,請參閱 advanced 部分。

警告

強烈建議您在 binary mode . 這是因為請求可能試圖提供 Content-Length 頭,如果它這樣做,這個值將被設置為 bytes 在文件中。如果在中打開文件,可能會發生錯誤。 文本模式.

響應狀態代碼?

我們可以檢查響應狀態代碼:

>>> r = requests.get('https://httpbin.org/get')
>>> r.status_code
200

請求還附帶一個內置的狀態代碼查找對象,以便于參考:

>>> r.status_code == requests.codes.ok
True

如果我們提出了一個錯誤的請求(4xx客戶機錯誤或5xx服務器錯誤響應),我們可以使用 Response.raise_for_status() ::

>>> bad_r = requests.get('https://httpbin.org/status/404')
>>> bad_r.status_code
404

>>> bad_r.raise_for_status()
Traceback (most recent call last):
  File "requests/models.py", line 832, in raise_for_status
    raise http_error
requests.exceptions.HTTPError: 404 Client Error

但是,自從我們 status_code 對于 r200 當我們呼喚 raise_for_status() 我們得到:

>>> r.raise_for_status()
None

一切都好。

響應頭?

我們可以使用python字典查看服務器的響應頭:

>>> r.headers
{
    'content-encoding': 'gzip',
    'transfer-encoding': 'chunked',
    'connection': 'close',
    'server': 'nginx/1.0.4',
    'x-runtime': '148ms',
    'etag': '"e1ca502697e5c9317743dc078f67693f"',
    'content-type': 'application/json'
}

不過,字典是特殊的:它只是為HTTP頭編寫的。根據 RFC 7230 ,HTTP頭名稱不區分大小寫。

因此,我們可以使用所需的任何大小寫訪問標題:

>>> r.headers['Content-Type']
'application/json'

>>> r.headers.get('content-type')
'application/json'

服務器可以多次發送具有不同值的同一頭文件,這一點也很特殊,但是請求將它們組合在一起,以便在一個映射中用字典表示,如 RFC 7230

收件人可以將具有相同字段名的多個頭字段組合成一對“字段名:字段值”,而不更改消息的語義,方法是將每個后續字段值依次附加到組合字段值上,用逗號分隔。

Cookies?

如果響應包含一些cookie,您可以快速訪問它們:

>>> url = 'http://example.com/some/cookie/setting/url'
>>> r = requests.get(url)

>>> r.cookies['example_cookie_name']
'example_cookie_value'

要將自己的cookie發送到服務器,可以使用 cookies 參數::

>>> url = 'https://httpbin.org/cookies'
>>> cookies = dict(cookies_are='working')

>>> r = requests.get(url, cookies=cookies)
>>> r.text
'{"cookies": {"cookies_are": "working"}}'

cookies將在 RequestsCookieJar 就像一個 dict 但也提供了一個更完整的接口,適合在多個域或路徑上使用。也可以將cookie jar傳遞到請求:

>>> jar = requests.cookies.RequestsCookieJar()
>>> jar.set('tasty_cookie', 'yum', domain='httpbin.org', path='/cookies')
>>> jar.set('gross_cookie', 'blech', domain='httpbin.org', path='/elsewhere')
>>> url = 'https://httpbin.org/cookies'
>>> r = requests.get(url, cookies=jar)
>>> r.text
'{"cookies": {"tasty_cookie": "yum"}}'

重定向和歷史記錄?

默認情況下,請求將為除head以外的所有謂詞執行位置重定向。

我們可以使用 history 要跟蹤重定向的響應對象的屬性。

這個 Response.history 列表包含 Response 為完成請求而創建的對象。列表從最早的響應到最新的響應進行排序。

例如,Github將所有HTTP請求重定向到https::

>>> r = requests.get('http://github.com/')

>>> r.url
'https://github.com/'

>>> r.status_code
200

>>> r.history
[<Response [301]>]

如果使用get、options、post、put、patch或delete,則可以使用 allow_redirects 參數::

>>> r = requests.get('http://github.com/', allow_redirects=False)

>>> r.status_code
301

>>> r.history
[]

如果使用head,也可以啟用重定向::

>>> r = requests.head('http://github.com/', allow_redirects=True)

>>> r.url
'https://github.com/'

>>> r.history
[<Response [301]>]

超時?

您可以告訴請求在給定的秒數后停止等待響應 timeout 參數。幾乎所有的生產代碼都應該在幾乎所有的請求中使用這個參數。不這樣做會導致程序無限期掛起:

>>> requests.get('https://github.com/', timeout=0.001)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
requests.exceptions.Timeout: HTTPConnectionPool(host='github.com', port=80): Request timed out. (timeout=0.001)

注意

timeout 不是整個響應下載的時間限制;相反,如果服務器沒有為發出響應,則會引發異常 timeout 秒(更準確地說,如果在基礎套接字上沒有接收到 timeout 秒)。如果沒有顯式指定超時,則請求不會超時。

錯誤和異常?

如果出現網絡問題(如DNS故障、拒絕連接等),請求將引發 ConnectionError 例外。

Response.raise_for_status() 將提高 HTTPError 如果HTTP請求返回不成功的狀態代碼。

如果請求超時,則 Timeout 引發異常。

如果請求超過配置的最大重定向次數,則 TooManyRedirects 引發異常。

請求顯式引發的所有異常都繼承自 requests.exceptions.RequestException .


準備好了嗎?退房 advanced 部分。

如果你在就業市場,考慮接受 this programming quiz . 如果你通過這個平臺找到一份工作,我們將為這個項目提供大量的捐贈。