[基礎]-requests模組使用詳解
參考官方文件:http://www.python-requests.org/en/master/
目錄
六、POST一個多部分編碼(Multipart-Encoded)的檔案
模組匯入:
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 木風卜雨========================================