python+requests

weixin_33749242發表於2018-04-10

【requests傳送請求引言】

使用 Requests 傳送網路請求非常簡單。

一開始要匯入 Requests 模組:

 >>import requests

然後,嘗試獲取某個網頁。本例子中,我們來獲取 Github 的公共時間線:

>>> r = requests.get('https://api.github.com/events')
>>> print (r)
<Response [200]>

現在,我們有一個名為 rResponse 物件。
我們可以從這個物件中獲取所有我們想要的資訊。

Requests 簡便的 API 意味著所有 HTTP 請求型別都是顯而易見的。
例如,你可以這樣傳送一個 HTTP POST 請求:

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

漂亮,對吧?那麼其他 HTTP 請求型別:PUT,DELETE,HEAD 以及 OPTIONS 又是如何的呢?都是一樣的簡單:

>> 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')

都很不錯吧,但這也僅是 Requests 的冰山一角呢。

一、【響應內容】

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

#1.響應狀態碼
>>> r.status_code
200

#2.為方便引用,Requests還附帶了一個內建的狀態碼查詢物件
>>> r.status_code == requests.codes.ok
True

#3.文字響應內容
>>> r.text
u'[{"repository":{"open_issues":0,"url":"https://github.com/...

#4.JSON 響應內容
Requests 中也有一個內建的 JSON 解碼器,助你處理 JSON 資料
>>> r.json()
[{u'repository': {u'open_issues': 0, u'url': 'https://github.com/...

#5.原始響應內容(極少使用)
>>> r.raw
<requests.packages.urllib3.response.HTTPResponse object at 0x101194810>
>>> r.raw.read(10)
'\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\x03'

#6. 響應頭
我們可以檢視以一個 Python 字典形式展示的伺服器響應頭
>>> r.headers
{
    'content-encoding': 'gzip',
    'transfer-encoding': 'chunked',
    'server': 'nginx/1.0.4',
    'content-type': 'application/json'
}

#7.也使用任意大寫形式來訪問這些響應頭欄位
>>> r.headers['Content-Type']
'application/json'

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

#8.訪問響應欄位中的cookies
>>> r.cookies['example_cookie_name']
'example_cookie_value'

#9.傳送你的cookies到伺服器,可以使用 cookies 引數:
>>> url = 'http://httpbin.org/cookies'
>>> cookies = dict(cookies_are='working')

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

二、【傳送請求】

1.普通的請求(如上所示)

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

2.傳遞 URL 引數的請求

Requests 允許你使用 params 關鍵字引數,以一個字串字典來提供這些引數

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

通過列印輸出該 URL,你能看到 URL 已被正確編碼:

>>> print(r.url)
http://httpbin.org/get?key2=value2&key1=value1
2.1還可以將一個列表作為值傳入:

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

定製請求頭headers

如果你想為請求新增 HTTP 頭部,只要簡單地傳遞一個 dict 給 headers 引數就可以了

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

>>> r = requests.get(url, headers=headers)
>>> r.url
'https://api.github.com/some/endpoint'

3.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 版的新加功能:

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

POST一個多部分編碼檔案

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

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

你可以顯式地設定檔名,檔案型別和請求頭

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

你也可以傳送作為檔案來接收的字串

>>> files = {'file': ('report.csv', 'some,data,to,send\nanother,row,to,send\n')}

【擴充】
參考連結
傳送POST請求
一個http請求包括三個部分,為別為請求行,請求報頭,訊息主體,類似以下這樣:

請求行
請求報頭
訊息主體

HTTP協議規定post提交的資料必須放在訊息主體中,但是協議並沒有規定必須使用什麼編碼方式。服務端通過是根據請求頭中的Content-Type欄位來獲知請求中的訊息主體是用何種方式進行編碼,再對訊息主體進行解析。具體的編碼方式包括:

  • application/x-www-form-urlencoded
    最常見post提交資料的方式,以form表單形式提交資料。
  • application/json
    以json串提交資料。
  • multipart/form-data
    一般使用來上傳檔案。

2.7.1 以form形式傳送post請求

Reqeusts支援以form表單形式傳送post請求,只需要將請求的引數構造成一個字典,然後傳給requests.post()的data引數即可。

url = 'http://httpbin.org/post'
d = {'key1': 'value1', 'key2': 'value2'}
r = requests.post(url, data=d)
print r.text

輸出:

{
“args”: {},
“data”: “”,
“files”: {},
“form”: {
“key1”: “value1”,
“key2”: “value2”
},
“headers”: {
……
“Content-Type”: “application/x-www-form-urlencoded”,
……
},
“json”: null,
……
}

可以看到,請求頭中的Content-Type欄位已設定為application/x-www-form-urlencoded,且d = {'key1': 'value1', 'key2': 'value2'}以form表單的形式提交到服務端,服務端返回的form欄位即是提交的資料。

2.7.2 以json形式傳送post請求

可以將一json串傳給requests.post()的data引數,

url = 'http://httpbin.org/post'
s = json.dumps({'key1': 'value1', 'key2': 'value2'})
r = requests.post(url, data=s)
print r.text

輸出:

{
“args”: {},
“data”: “{\”key2\”: \”value2\”, \”key1\”: \”value1\”}”,
“files”: {},
“form”: {},
“headers”: {
……
“Content-Type”: “application/json”,
……
},
“json”: {
“key1”: “value1”,
“key2”: “value2”
},
……
}

可以看到,請求頭的Content-Type設定為application/json,並將s這個json串提交到服務端中。

2.7.3 以multipart形式傳送post請求

Requests也支援以multipart形式傳送post請求,只需將一檔案傳給requests.post()的files引數即可。

url = 'http://httpbin.org/post'
files = {'file': open('report.txt', 'rb')}
r = requests.post(url, files=files)
print r.text

輸出:

{
“args”: {},
“data”: “”,
“files”: {
“file”: “Hello world!”
},
“form”: {},
“headers”: {……
“Content-Type”: “multipart/form-data; boundary=467e443f4c3d403c8559e2ebd009bf4a”,
……
},
“json”: null,
……
}

文字檔案report.txt的內容只有一行:Hello world!,從請求的響應結果可以看到資料已上傳到服務端中。

2.8 Cookie設定

使用requests,可以輕鬆獲取響應的cookies,和設定請求的cookies。

2.8.1 獲取響應的cookies

r.cookies是響應cookies的字典,通過r.cookies可訪問響應帶上的cookies。

r = requests.get(url)
print r.cookies['example_cookie_name']

2.8.2 傳送帶cookies的請求

url = 'http://httpbin.org/cookies'
cookies = {'cookies_are': 'working'}
r = requests.get(url, cookies=cookies)
print r.text

輸出:

{
“cookies”: {
“cookies_are”: “working”
}
}

2.9 請求的超時設定

Requests允許對一個http請求設定超時的時間,只需要在requests.get()或者requests.post()方法的timeout引數設定一個值(單位為秒)即可。

url = 'http://httpbin.org/get'
r = requests.get(url, timeout=0.001)

將會丟擲一個超時異常:

raise ConnectTimeout(e, request=request)
requests.exceptions.ConnectTimeout: HTTPConnectionPool(host=’httpbin.org’, port=80): Max retries exceeded with url: /get (Caused by ConnectTimeoutError(

2.10 異常

在傳送http請求時,由於各種原因,requests可能會請求失敗而丟擲異常。常見的異常包括:

  • ConnectionError
    由於網路原因,無法建立連線。
  • HTTPError
    如果響應的狀態碼不為200,Response.raise_for_status()會丟擲HTTPError 異常。
  • Timeout
    超時異常。
  • TooManyRedirects
    若請求超過了設定的最大重定向次數,則會丟擲一個 TooManyRedirects 異常。

所有requests丟擲的異常都繼承自 requests.exceptions.RequestException類。