requests
一、簡介
使用 Python 做自動化接口測試需要用代碼發送 http 請求。requests 是 Python 語言里網絡請求庫中最好用的,沒有之一。
requests 庫有完善詳盡的中文版官方文檔:
https://requests.readthedocs.io/zh_CN/latest/
作者
Requests 的作者 Kenneth Reitz 是一個富有傳奇色彩的人物。
Kenneth Reitz 在有著“云服務鼻祖”之稱的 Heroku 公司,28 歲時就擔任了 Python 語言的總架構師。他做了什么呢?隨便列幾個項目名稱: requests、python-guide、pipenv、legit、autoenv,當然它也給 Python 界很多知名的開源項目貢獻了代碼,比如 Flask。大神級程序員,據說其身價高達 5 億美元。
二、使用
1. 發起請求
1.1 請求方法
每一個請求方法都有一個對應的 API,比如 GET 請求就可以使用 get() 方法:
import requests
resp = requests.get('https://www.baidu.com')
而 POST 請求就可以使用 post() 方法,并且將需要提交的數據傳遞給 data 參數即可:
resp = requests.post('http://httpbin.org/post', data = {'key':'value'})
而其他的請求類型,都有各自對應的方法:
requests.put('http://httpbin.org/put', data = {'key':'value'})
requests.delete('http://httpbin.org/delete')
requests.head('http://httpbin.org/get')
requests.options('http://httpbin.org/get')
非常的簡單直觀明了。
1.2 傳遞 URL 參數
傳遞 URL 參數不需要去拼接 URL,而是簡單的,構造一個字典,并在請求時將其傳遞給 params 參數:
import requests
params = {'key1': 'value1', 'key2': 'value2'}
resp = requests.get("http://httpbin.org/get", params=params)
此時,查看請求的 URL,則可以看到 URL 已經構造正確了:
print(resp.url)
http://httpbin.org/get?key1=value1&key2=value2
并且,有時候我們會遇到相同的 url 參數名,但有不同的值,而 python 的字典又不支持鍵的重名,那么我們可以把鍵的值用列表表示:
params = {'key1': 'value1', 'key2': ['value2', 'value3']}
resp = requests.get('http://httpbin.org/get', params=params)
print(resp.url)
http://httpbin.org/get?key1=value1&key2=value2&key2=value3
注:http://httpbin.org 是 Kenneth Reitz 搭建的為測試 http 服務而寫的項目
1.3 傳遞表單參數
通常,你想要發送一些編碼為表單形式的數據——非常像一個 html 表單。
要實現這個,只需簡單地傳遞一個字典給 data 參數。你的數據字典在發出請求時會自動編碼為表單形式:
resp = requests.post('http://httpbin.org/post', data = {'key':'value'})
resp.json()
{'args': {},
'data': '',
'files': {},
'form': {'key': 'value'},
'headers': {'Accept': '/',
'Accept-Encoding': 'gzip, deflate',
'Content-Length': '9',
'Content-Type': 'Application/x-www-form-urlencoded',
'Host': 'httpbin.org',
'User-Agent': 'python-requests/2.23.0',
'X-Amzn-Trace-Id': 'Root=1-5f620401-c24c466c4e6fac3ee0fda64d'},
'json': None,
'origin': '113.246.106.31',
'url': 'http://httpbin.org/post'}
1.4 傳遞 JSON 參數
使用 json 參數直接傳遞,然后它就會被自動編碼。這是 2.4.2 版的新加功能:
resp = requests.post('http://httpbin.org/post', json = {'key':'value'})
resp.json()
{'args': {},
'data': '{"key": "value"}',
'files': {},
'form': {},
'headers': {'Accept': '/',
'Accept-Encoding': 'gzip, deflate',
'Content-Length': '16',
'Content-Type': 'application/json',
'Host': 'httpbin.org',
'User-Agent': 'python-requests/2.23.0',
'X-Amzn-Trace-Id': 'Root=1-5f620443-9d8785d6ee6f444a67a162f8'},
'json': {'key': 'value'},
'origin': '113.246.106.31',
'url': 'http://httpbin.org/post'}
1.5 上傳文件
使用 files 參數傳遞文件句柄
url = 'http://httpbin.org/post'
files = {'file': open('test.xls', 'rb')}
r = requests.post(url, files=files)
r.text
1.6 自定義 Headers
如果想自定義請求的 Headers,同樣的將字典數據傳遞給 headers 參數。
url = 'http://httpbin.org/get'
headers = {'user-agent': 'lemonban/0.0.1'}
resp = requests.get(url, headers=headers)
resp.json()
{'args': {},
'headers': {'Accept': '/',
'Accept-Encoding': 'gzip, deflate',
'Host': 'httpbin.org',
'User-Agent': 'lemonban/0.0.1',
'X-Amzn-Trace-Id': 'Root=1-5f6205a1-25641a90501e5911352a84c0'},
'origin': '113.246.106.31',
'url': 'http://httpbin.org/get'}
1.7 自定義 Cookies
Requests 中自定義 Cookies 也不用再去構造 CookieJar 對象,直接將字典遞給 cookies 參數。
url = 'http://httpbin.org/get'
cookies = {'cookies_are': 'working'}
resp = requests.get(url, cookies=cookies)
resp.json()
{'args': {},
'headers': {'Accept': '/',
'Accept-Encoding': 'gzip, deflate',
'Cookie': 'cookies_are=working',
'Host': 'httpbin.org',
'User-Agent': 'python-requests/2.23.0',
'X-Amzn-Trace-Id': 'Root=1-5f6205d9-03efd00833b145237185ded0'},
'origin': '113.246.106.31',
'url': 'http://httpbin.org/get'}
1.8 設置代理
當我們需要使用代理時,同樣構造代理字典,傳遞給 proxies 參數。
proxies = {
'http': 'http://10.10.1.10:3128',
'https': 'http://10.10.1.10:1080',
}
requests.get('http://example.org', proxies=proxies)
1.9 重定向
在網絡請求中,我們常常會遇到狀態碼是 3 開頭的重定向問題,在 Requests 中是默認開啟允許重定向的,即遇到重定向時,會自動繼續訪問。
resp = requests.get('http://github.com', allow_redirects=False)
resp.status_code
301
1.10 禁止證書驗證
有時候我們使用了抓包工具,這個時候由于抓包工具提供的證書并不是由受信任的數字證書頒發機構頒發的,所以證書的驗證會失敗,所以我們就需要關閉證書驗證。
在請求的時候把 verify 參數設置為 False 就可以關閉證書驗證了。
import requests
resp = requests.get('https://httpbin.org/get', verify=False)
但是關閉驗證后,會有一個比較煩人的 warning,可以使用以下方法關閉警告:
from requests.packages.urllib3.exceptions import InsecureRequestWarning
# 禁用安全請求警告
requests.packages.urllib3.disable_warnings(InsecureRequestWarning)
1.11 設置超時
設置訪問超時,設置 timeout 參數即可。
requests.get('http://github.com', timeout=0.001)
可見,通過 Requests 發起請求,只需要構造好幾個需要的字典,并將其傳入請求的方法中,即可完成基本的網絡請求。
2. 響應
通過 Requests 發起請求獲取到的,是一個 requests.models.Response 對象。通過這個對象我們可以很方便的獲取響應的內容。
2.1 響應數據
通過 Response 對象的 text 屬性可以獲得字符串格式的響應內容。
import requests
resp = requests.get('https://www.baidu.com')
resp.text
Requests 會自動的根據響應的報頭來猜測網頁的編碼是什么,然后根據猜測的編碼來解碼網頁內容,基本上大部分的網頁都能夠正確的被解碼。而如果發現 text 解碼不正確的時候,就需要我們自己手動的去指定解碼的編碼格式。
import requests
resp = requests.get('https://www.baidu.com')
resp.encoding = 'utf-8' # 設置編碼
resp.text
而如果你需要獲得原始的二進制數據,那么使用 content 屬性即可。
resp.content
如果我們訪問之后獲得的數據是 JSON 格式的,那么我們可以使用 json() 方法,直接獲取轉換成字典格式的數據。
resp = requests.get('http://httpbin.org/get')
resp.json()
{'args': {},
'headers': {'Accept': '/',
'Accept-Encoding': 'gzip, deflate',
'Host': 'httpbin.org',
'User-Agent': 'python-requests/2.23.0',
'X-Amzn-Trace-Id': 'Root=1-5f62083f-6b0db04c94aff004d15c0068'},
'origin': '113.246.106.31',
'url': 'http://httpbin.org/get'}
2.2 狀態碼
通過 status_code 屬性獲取響應的狀態碼
resp = requests.get('http://httpbin.org/get')
resp.status_code
200
2.4 響應報頭
通過 headers 屬性獲取響應的報頭
resp.headers
{'Date': 'Wed, 16 Sep 2020 12:43:17 GMT', 'Content-Type': 'application/json', 'Content-Length': '307', 'Connection': 'keep-alive', 'Server': 'gunicorn/19.9.0', 'Access-Control-Allow-Origin': '*', 'Access-Control-Allow-Credentials': 'true'}
2.5 服務器返回的 cookies
通過 cookies 屬性獲取服務器返回的 cookies
import requests
url = 'http://www.baidu.com'
resp = requests.get(url)
resp.cookies
<RequestsCookieJar[Cookie(version=0, name='BDORZ', value='27315', port=None, port_specified=False, domain='.baidu.com', domain_specified=True, domain_initial_dot=True, path='/', path_specified=True, secure=False, expires=1600346744, discard=False, comment=None, comment_url=None, rest={}, rfc2109=False)]>
2.6 url
還可以使用 url 屬性查看訪問的 url。
params = {'key1': 'value1', 'key2': 'value2'}
resp = requests.get("http://httpbin.org/get", params=params)
resp.url
'http://httpbin.org/get?key1=value1&key2=value2'
3. Session
在 Requests 中,實現了 Session(會話) 功能,當我們使用 Session 時,能夠像瀏覽器一樣,在沒有關閉關閉瀏覽器時,能夠保持住訪問的狀態。
這個功能常常被我們用于登陸之后的數據獲取,使我們不用再一次又一次的傳遞 cookies。
import requests
session = requests.Session()
session.get('http://httpbin.org/cookies/set/sessioncookie/123456789')
resp = session.get('http://httpbin.org/cookies')
print(resp.text)
{
"cookies": {
"sessioncookie": "123456789"
}
}
首先我們需要去生成一個 Session 對象,然后用這個 Session 對象來發起訪問,發起訪問的方法與正常的請求是一摸一樣的。
同時,需要注意的是,如果是我們在 get() 方法中傳入 headers 和 cookies 等數據,那么這些數據只在當前這一次請求中有效。如果你想要讓一個 headers 在 Session 的整個生命周期內都有效的話,需要用以下的方式來進行設置:
# 設置整個headers
session.headers = {
'user-agent': 'lemonban/0.0.1'
}
# 增加一條headers
session.headers.update({'x-test': 'true'})