1. 程式人生 > >[基礎]-requests模組使用詳解

[基礎]-requests模組使用詳解

 

參考官方文件:http://www.python-requests.org/en/master/

目錄

一、傳送請求

傳送GET請求:

傳送POST請求

傳送put請求

傳送delete請求

傳送head請求

傳送options請求

二、傳遞URL引數

以字典形式作引數輸入

將一個列表作為值傳入

三、響應內容

 二進位制響應內容

JSON響應內容

原始響應內容

四、定製請求頭

五、 更加複雜的POST請求

六、POST一個多部分編碼(Multipart-Encoded)的檔案

七、響應頭

八、Cookie

 獲取cookie

 傳送cookeis到伺服器

九、重定向與請求歷史

十、超時

十一、錯誤與異常

十二,HTTPBasicAuth




模組匯入:
import requests

一、傳送請求

傳送GET請求:

獲取GITHUB的公共時間線

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

現在r為response物件,從這個物件可以獲取想要的資訊

傳送POST請求

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

傳送put請求

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

傳送delete請求

r = requests.delete(url='http://httpbin.org/delete’)

傳送head請求

r = requests.head(url='http://httpbin.org/get')

傳送options請求

r = requests.optinos(url='http://httpbin.org/get')

以上為request的基本用法。

 

二、傳遞URL引數

以字典形式作引數輸入

Requests允許使用params關鍵字引數,以一個字串字典來提供,比如:傳遞 key1=value1 和 key2=value2 到 httpbin.org/get,程式碼如下:

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

輸入新的url:

print(r.url)

http://httpbin.org/get?key1=value1&key2=value2

注意:以上字典裡如果出現值為None,那麼健不會被新增到URL的查詢字串裡

 

將一個列表作為值傳入

Pload = {'key1':'value1','key2':['value2','value3']}
r = requests.get('http://httpbin.org/get', params=Pload)

輸入新的url:

print(r.url)

http://httpbin.org/get?key1=value1&key2=value2&key2=value3

 

三、響應內容

讀取伺服器響應的內容,以GITHUB時間線為例

import requests

r = requests.get(url='https://api.github.com/events')
print(r.text)
[{"id":"7610277004","type":"IssuesEvent","actor":{"id":1049678,"login":"tkurki","display_login":"tkurki","gravatar_id":"","url":"https://api.github.com/users/tkurki","avatar_url":"https://avatars.githubusercontent.com/u/1049678?"},"repo":{"id":58462216,"name":"vazco/uniforms","url":"https://api.github.com/repos/vazco/uniforms"},"payload":{"action":"opened",…………

 

Requests會自動解碼來自伺服器的內容,大多數unicode字符集都能被無縫的解碼。

請求發出後,requests會基於HTTP頭部對響應的編碼作出有根據的推測,當你訪問r.text之時,request會基於其推斷的文字進行編碼,你可以找出request使用了什麼編碼,並且能夠使用r.encoding屬性修改它

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

#輸出預設編碼:utf-8
print(r.encoding)

r.encoding='ISO-8859-1'
#輸出修改後使用的編碼:ISO-8859-1
print(r.encoding)

當修改編碼後,每當使用r.text,requests都將使用r.encoding的新值。

比如:HTTP,XML自身可以指定編碼,這樣的話,可以通過r.content來找到編碼,然後設定 r.encoding 為相應的編碼,這樣就能使用正確的編碼解析r.text

r = requests.get(url='http://www.etongbao.com.cn')
r.content
b'<!DOCTYPE html>\n<html lang="zh-CN">\n  <head>\n    <meta charset="utf-8">\n  …..

以BYTES型別列印頁面所有內容

 

 二進位制響應內容

r.content
b'<!DOCTYPE html>\n<html lang="zh-CN">\n  <head>\n    <meta charset="utf-8">\n  …..

 

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(url='https://api.github.com/events')
print(type(r.json()))
print(r.json())

輸出:

<class 'dict'>

{'message': "API rate limit exceede

如果r.jsnon解析失敗,r.json會丟擲一個異常,如:ValueError: No JSON object could be decoded 異常,但是,有個伺服器在失敗的響應中也包含一個json物件,這種json會被解碼返回,要檢查請求是否成功,請使用:

r.raise_for_status() 或者 檢查r.status_code 是否和期望值相同。

 

原始響應內容

獲取來自伺服器的原始套接字響應,需要在初始請求中設定:stream=True

import requests

r = requests.get(url='https://api.github.com/events', stream = True)
print(r.raw)
返回:<urllib3.response.HTTPResponse object at 0x023C12F0> 物件

print(r.raw.read(10))

返回:b'\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\x03'  返回原始10位元組內容

 

一般情況,以下面方式儲存文字流

import requests

r = requests.get(url='https://api.github.com/events', stream = True)
with open('test', 'wb') as fb:
    for chunk in r.iter_content(chunk_size):
        fb.write(chunk)

使用r.iter_content將會處理大量你直接使用r.raw不得不處理的內容。

 

四、定製請求頭

為請求新增HTTP頭部,通過傳遞一個dict給headers引數即可。

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

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

l   如果在.netrc中設定了使用者認證資訊,使用headers=設定的授權就不會生效。而如果設定了auth=引數,’’.netrc’’的設定就無效了

l   如果被重定向到別的主機,授權header就會被刪除

l   代理授權header會被URL中提供的代理身份覆蓋掉

l   在我們能判斷內容長度的情況下,header的content-length會被改寫

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

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

 

五、 更加複雜的POST請求

傳送編碼為表單形式的資料,只需將一個字典傳遞給data引數,資料字典在傳送請求時會自動編碼為表單形式:

import requests

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

輸出:

  "form": {

    "key1": "value1",
    "key2": "value2"

  },

 

可以為data引數傳入一個元祖引數,在表單中多個元素使用同一個key的時候,方式如下:

import requests

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

輸出:

  "form": {
    "key1": [
      "value1",
      "value2"
    ]
  },

 

如果傳遞的是字串,非dict,那麼資料會被直接傳送出去。

例如:github api v3接受編碼為json的POST/PATCH資料

import requests,json

url = 'https://api.github.com/some/endpoint'
payload = {'sone':'data'}
r = requests.post(url, data=json.dumps(payload))

 

使用json引數直接傳遞,然後它就會被自動編碼,這是2.4.2版新加功能

import requests,json

url = 'https://api.github.com/some/endpoint'
payload = {'sone':'data'}
r = requests.post(url, json=payload)

這裡payload會被自動轉化為json格式,

data=json.dumps(payload) == json=payload  這2個是相同的結果

 

六、POST一個多部分編碼(Multipart-Encoded)的檔案

Requests使上傳多部分編碼檔案變得簡單

import requests,json

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

輸出:

{  "files": {
    "file": "zhaoyong\r\nzhaoyong\r\nzhaoyong"
  },
}

 

顯示設定檔名,檔案型別和請求頭

import requests,json

url = 'http://httpbin.org/post'
files = {'file':('t1', open('t1','rb'), 'application/vnd.ms-excel', {'Expires': '0'})}
r = requests.post(url, files=files)
print(r.text)

 

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

import requests,json

url = 'http://httpbin.org/post'
files = {'file':('t2','zhaoyong,zhoayong,zhaoyong')}
r = requests.post(url, files=files)
print(r.text)

輸出:

  "files": {
    "file": "zhaoyong,zhoayong,zhaoyong"
  },

 

如果傳送非常大的檔案作為 multipart/form-data請求,預設情況requests不支援做成資料流,有個第三方包:requests-toolbelt支援,參閱:toolbelt文件,http://toolbelt.readthedocs.io/en/latest/

 

一個請求傳送多檔案參考:http://docs.python-requests.org/zh_CN/latest/user/advanced.html#advanced

 

警告:一定要用二進位制模式開啟檔案,因為requests可能會試圖為你提供Content-Length header,這個值會被設為檔案的位元組數,如果用文字模式開啟,可能會發生錯誤。

 

 響應狀態碼

檢測響應狀態碼:

import requests,json

r = requests.get(url='http://httpbin.org/get')
print(r.status_code)

輸出:200

 

一個錯誤請求,使用raise_for_status()來丟擲異常,無異常輸出為None

import requests,json

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

輸出:404

bad_r.raise_for_status()

輸出:

Traceback (most recent call last):
  File "D:/AutoCobbler/dellIdrac/idrac_api.py", line 35, in <module>
    bad_r.raise_for_status()
  File "C:\Python36-32\lib\site-packages\requests\models.py", line 935, in raise_for_status
    raise HTTPError(http_error_msg, response=self)
requests.exceptions.HTTPError: 404 Client Error: NOT FOUND for url: http://httpbin.org/status/404

七、響應頭

r.headers  : 會以python字典形式展示伺服器的響應頭

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

注:HTTP頭部大小寫不敏感

因此,可以使用任意大寫形式訪問這些響應頭欄位

url = 'http://httpbin.org/post'

files = {'file':('t2','zhaoyong,zhoayong,zhaoyong')}

r = requests.post(url, files=files)

print(r.headers['content-type'])  # 以字典形式列印
print(r.headers.get('content-type'))  # 通過get獲取資料

特殊點,伺服器可以多次接受同一header,每次都使用不同的值,但requests會將它們合併,這樣他們就可以用一個對映來表示出來。


八、Cookie


 獲取cookie

import requests

url = 'http://example.com/some/cookie/setting/url'
r = requests.get(url)
r.cookies
#獲取字典形式的cookie
r.cookies.get_dict()

 傳送cookeis到伺服器

import requests

url = 'http://httpbin.org/cookies'
cookies = dict(cookies_are = 'working')
r = requests.get(url, cookies = cookies)
print(r.text)
輸出:
{
  "cookies": {
    "cookies_are": "working"
  }
}
Cookies的返回物件為RequestsCookieJar,它和字典類似,適合跨域名跨路勁使用,可以把cookiejar傳到requests中。
import requests

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 = 'http://httpbin.org/cookies'
r = requests.get(url, cookies=jar)
print(r.text)
輸出:
{
  "cookies": {
    "tasty_cookie": "yum"
  }
}

九、重定向與請求歷史

除了使用head, requests自動處理重定向,還可用history來追蹤重定向。
Response.history是一個response物件的列表,為了完成請求而建立了這些物件,這個物件的列表按照從最老到最近的請求進行排序。
import requests

r = requests.get(url='http://github.com')
print(r.url)
print(r.status_code)
print(r.history)
輸出:
https://github.com/
200
[<Response [301]>]
如果使用的是:GET,POST,OPTIONS,PUT,PATCH或者DELETE,可以通過allow_redirects引數禁用重定向處理。
import requests

r = requests.get(url='http://github.com', allow_redirects=False)
print(r.url)
print(r.history)
輸出:
http://github.com/
[]
如果使用HEAD,也可以啟動重定向
import requests

r = requests.head(url='http://github.com', allow_redirects=True)
print(r.url)
print(r.history)
輸出:
https://github.com/
[<Response [301]>]

十、超時

Requests以timeout引數設定的秒數時間之後停止等待響應,如果不設定,程式有可能永遠失去響應。
import requests

r = requests.head(url='http://github.com', timeout=0.001)
輸出:
requests.exceptions.ConnectTimeout: HTTPConnectionPool(host='github.com', port=80): Max retries exceeded with url:......................
注意:timeout只對連線過程有效,與響應體的下載無關,timeout並不是整個下載響應的時間限制,而是如果伺服器在timeout秒內沒有應答,將會引發一個異常(精確的說,在timeout秒內沒有從基礎套接字上接收到任何位元組的資料時)

十一、錯誤與異常

如遇網路問題(DNS查詢失敗,拒絕連線等)時,requests會丟擲一個ConnectionError異常。

如果HTTP請求返回了不成功的狀態碼,response.raise_for_status()會丟擲一個HTTPError異常。

若請求超時,則丟擲一個timeout異常。

若請求超過了設定的最大重定向次數,則會丟擲一個TooManyRedirects異常。

所有requests顯示丟擲的異常都繼承自requests.exceptions.RequestException
 

十二,HTTPBasicAuth

有時訪問一些網站時會彈出登入框,類似我們訪問路由器192.168.1.1時彈出的登入框一樣,這類是瀏覽器彈出的固定模式登入框,並不是網站,所以抓包時並不會看到登入URL。碰到這情況,用如下方式解決“:

import requests
from requests.auth import HTTPBasicAuth

r = requests.get(url='',auth=HTTPBasicAuth('your account','your pw'))

 

========================================end 木風卜雨========================================

========================================end 木風卜雨========================================