Requests 響應內(nèi)容

2022-06-27 15:27 更新

我們能讀取服務器響應的內(nèi)容。再次以 GitHub 時間線為例:

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

Requests 會自動解碼來自服務器的內(nèi)容。大多數(shù) unicode 字符集都能被無縫地解碼。

請求發(fā)出后,Requests 會基于 HTTP 頭部對響應的編碼作出有根據(jù)的推測。當你訪問 ?r.text? 之時,Requests 會使用其推測的文本編碼。你可以找出 Requests 使用了什么編碼,并且能夠使用 ?r.encoding? 屬性來改變它:

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

如果你改變了編碼,每當你訪問 ?r.text? ,Request 都將會使用 ?r.encoding? 的新值。你可能希望在使用特殊邏輯計算出文本的編碼的情況下來修改編碼。比如 HTTP 和 XML 自身可以指定編碼。這樣的話,你應該使用 r.content 來找到編碼,然后設(shè)置 ?r.encoding? 為相應的編碼。這樣就能使用正確的編碼解析 ?r.text? 了。

在你需要的情況下,Requests 也可以使用定制的編碼。如果你創(chuàng)建了自己的編碼,并使用 codecs 模塊進行注冊,你就可以輕松地使用這個解碼器名稱作為 ?r.encoding? 的值, 然后由 Requests 來為你處理編碼。

二進制響應內(nèi)容

你也能以字節(jié)的方式訪問請求響應體,對于非文本請求:

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

Requests 會自動為你解碼 gzip 和 deflate 傳輸編碼的響應數(shù)據(jù)。

例如,以請求返回的二進制數(shù)據(jù)創(chuàng)建一張圖片,你可以使用如下代碼:

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

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

JSON 響應內(nèi)容

Requests 中也有一個內(nèi)置的 JSON 解碼器,助你處理 JSON 數(shù)據(jù):

>>> 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()? 就會拋出一個異常。例如,響應內(nèi)容是 401 (Unauthorized),嘗試訪問 ?r.json()? 將會拋出 ?ValueError: No JSON object could be decoded? 異常。

需要注意的是,成功調(diào)用 ?r.json()? 并**不**意味著響應的成功。有的服務器會在失敗的響應中包含一個 JSON 對象(比如 HTTP 500 的錯誤細節(jié))。這種 JSON 會被解碼返回。要檢查請求是否成功,請使用 ?r.raise_for_status()? 或者檢查 ?r.status_code? 是否和你的期望相同。

原始響應內(nèi)容

在罕見的情況下,你可能想獲取來自服務器的原始套接字響應,那么你可以訪問 ?r.raw?。 如果你確實想這么干,那請你確保在初始請求中設(shè)置了 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? 不得不處理的。 當流下載時,上面是優(yōu)先推薦的獲取內(nèi)容方式。?請注意,chunk_size可以自由調(diào)整為可能更適合您的用例的數(shù)字。?

以上內(nèi)容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號