一焙格、簡(jiǎn)介
requests庫(kù)是 python 用來(lái)發(fā)送 http 請(qǐng)求。它是 Python 語(yǔ)言里網(wǎng)絡(luò)請(qǐng)求庫(kù)中最好用的井氢,沒(méi)有之一腾务。
requests 庫(kù)有完善詳盡的[官方文檔]https://docs.python-requests.org/zh_CN/latest/?utm_source=testingpai.com
二、發(fā)送請(qǐng)求
1 請(qǐng)求方法
每一個(gè)請(qǐng)求方法都有一個(gè)對(duì)應(yīng)的 API驴娃,比如 GET 請(qǐng)求就可以使用 get() 方法
import requests
resp = requests.get('https://www.baidu.com')
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')
常用的請(qǐng)求方法是get請(qǐng)求和post請(qǐng)求
1.1 傳遞URL參數(shù)(針對(duì)get請(qǐng)求)
get請(qǐng)求有兩種情況奏候,一種是沒(méi)有帶參數(shù)的,比如唇敞,請(qǐng)求百度首頁(yè)
resp = requests.get('https://www.baidu.com')
另一種是帶URL參數(shù)的蔗草,此時(shí)需要使用params關(guān)鍵字參數(shù)
payload = {'key1': 'value1', 'key2': 'value2'}
r = requests.get("http://httpbin.org/get", params=payload)
通過(guò)打印輸出該 URL咒彤,你能看到 URL 已被正確編碼:
print(r.url)
http://httpbin.org/get?key2=value2&key1=value1
有時(shí)候會(huì)遇到相同的 url 參數(shù)名,但有不同的值咒精,而 python 的字典又不支持鍵的重名镶柱,那么我們可以把鍵的值用列表表示:
payload = {'key1': 'value1', 'key2': ['value2', 'value3']}
r = requests.get('http://httpbin.org/get', params=payload)
print(r.url)
http://httpbin.org/get?key1=value1&key2=value2&key2=value3
1.2 傳遞表單參數(shù)(data 參數(shù))(針對(duì)post請(qǐng)求)
一般上post請(qǐng)求才有表單參數(shù),但是不是所有的post請(qǐng)求都是用表單參數(shù)
通常模叙,你想要發(fā)送一些編碼為表單形式的數(shù)據(jù)——非常像一個(gè) HTML 表單歇拆。
要實(shí)現(xiàn)這個(gè),只需簡(jiǎn)單地傳遞一個(gè)字典給 data 參數(shù)范咨。你的數(shù)據(jù)字典在發(fā)出請(qǐng)求時(shí)會(huì)自動(dòng)編碼為表單形式:
resp = requests.post('http://httpbin.org/post', data = {'key':'value'})
resp.json()
1.3 傳遞json參數(shù)
使用 json 參數(shù)直接傳遞故觅,然后它就會(huì)被自動(dòng)編碼
dic = {'key': 'value'} # 字典
resp = requests.post('http://httpbin.org/post', json=dic)
print(resp.json())
1.4 files參數(shù)上傳文件
url = 'http://httpbin.org/post'
files = {'file': open('test.xls', 'rb')}
r = requests.post(url, files=files)
r.text
1.5 自定義headers
自定義請(qǐng)求headers,把字典數(shù)據(jù)傳遞給 headers 參數(shù)
url = 'http://httpbin.org/get'
headers = {'user-agent': 'abc/0.0.1'}
resp = requests.get(url, headers=headers)
resp.json()
1.6 自定義 Cookies
Requests 中自定義 Cookies 也不用再去構(gòu)造 CookieJar 對(duì)象渠啊,直接將字典遞給 cookies 參數(shù)输吏。
url = 'http://httpbin.org/get'
cookies = {'cookies_are': 'working'}
resp = requests.get(url, cookies=cookies)
resp.json()
定義什么cookies就返回什么cookies
1.7 設(shè)置代理
當(dāng)我們需要使用代理時(shí),同樣構(gòu)造代理字典替蛉,傳遞給 proxies 參數(shù)贯溅。
proxies = {
'http': 'http://10.10.1.10:3128',
'https': 'http://10.10.1.10:1080',
}
requests.get('http://example.org', proxies=proxies)
http請(qǐng)求走h(yuǎn)ttp對(duì)應(yīng)的地址,https請(qǐng)求走h(yuǎn)ttps對(duì)應(yīng)的地址躲查,如果代理不支持https盗迟,即使key為https的地址寫了http開頭,也是不可用
VPN代理:
電腦開啟了VPN后熙含,要找到這個(gè)VPN的端口是什么罚缕,比如我的VPN占用的端口是:11000
Python代碼中這樣寫:
proxies = {
'http': 'http://127.0.0.1:11000',
'https': 'http://127.0.0.1:10000',
}
127.0.0.1就是本地的IP地址,上述設(shè)置中怎静,最好http和https都寫邮弹,單寫一個(gè)有可能代理不上
開啟fiddler后,不設(shè)置代理Python發(fā)送https請(qǐng)求也會(huì)失旘酒浮(請(qǐng)求http正常)腌乡,因?yàn)閒iddler也是一個(gè)代理軟件,需要設(shè)置代理(端口是fiddler中設(shè)置的夜牡,一般設(shè)置8888)
1.8 重定向
在網(wǎng)絡(luò)請(qǐng)求中与纽,我們常常會(huì)遇到狀態(tài)碼是 3 開頭的重定向問(wèn)題,在 Requests 中是默認(rèn)開啟允許重定向的塘装,即遇到重定向時(shí)急迂,會(huì)自動(dòng)繼續(xù)訪問(wèn)。
resp = requests.get('http://github.com', allow_redirects=False)
resp.status_code
1.9 禁止證書驗(yàn)證
方法1:
有時(shí)候我們使用了抓包工具蹦肴,這個(gè)時(shí)候由于抓包工具提供的證書并不是由受信任的數(shù)字證書頒發(fā)機(jī)構(gòu)頒發(fā)的僚碎,所以證書的驗(yàn)證會(huì)失敗,所以我們就需要關(guān)閉證書驗(yàn)證阴幌。
在請(qǐng)求的時(shí)候把 verify 參數(shù)設(shè)置為 False 就可以關(guān)閉證書驗(yàn)證了勺阐。
import requests
resp = requests.get('https://httpbin.org/get', verify=False)
但是關(guān)閉驗(yàn)證后卷中,會(huì)有一個(gè)比較煩人的 warning,可以使用以下方法關(guān)閉警告:
from requests.packages.urllib3.exceptions import InsecureRequestWarning
# 禁用安全請(qǐng)求警告
requests.packages.urllib3.disable_warnings(InsecureRequestWarning)
方法2:
在調(diào)試代碼的時(shí)候渊抽,經(jīng)常用到fiddler蟆豫,但是代碼本身不需要代理fiddler,這個(gè)時(shí)候添加下面代碼懒闷,在代碼請(qǐng)求的時(shí)候就不通過(guò)fiddler了十减,這樣就不用關(guān)閉fiddler了
import os
os.environ['NO_PROXY'] = 'stackoverflow.com'
如果代碼請(qǐng)求https要通過(guò)fiddler抓包,代碼需要設(shè)置代理毛雇,也要安裝證書(實(shí)際使用中嫉称,代碼已經(jīng)看到請(qǐng)求的參數(shù)了,一般不需要通過(guò)fiddler抓取代碼的請(qǐng)求)在調(diào)試代碼的時(shí)候灵疮,經(jīng)常用到fiddler织阅,但是代碼本身不需要代理fiddler,這個(gè)時(shí)候添加下面代碼震捣,在代碼請(qǐng)求的時(shí)候就不通過(guò)fiddler了荔棉,這樣就不用關(guān)閉fiddler了
import os
os.environ['NO_PROXY'] = 'stackoverflow.com'
如果代碼請(qǐng)求https要通過(guò)fiddler抓包,代碼需要設(shè)置代理蒿赢,也要安裝證書(實(shí)際使用中润樱,代碼已經(jīng)看到請(qǐng)求的參數(shù)了,一般不需要通過(guò)fiddler抓取代碼的請(qǐng)求)
1.10 設(shè)置超時(shí)
設(shè)置訪問(wèn)超時(shí)羡棵,設(shè)置 timeout 參數(shù)即可壹若。
requests.get('http://github.com', timeout=0.001)
上述可見,通過(guò) Requests 發(fā)起請(qǐng)求皂冰,只需要構(gòu)造好幾個(gè)需要的字典店展,并將其傳入請(qǐng)求的方法中,即可完成基本的網(wǎng)絡(luò)請(qǐng)求秃流。
2. 響應(yīng)
通過(guò) Requests 發(fā)起請(qǐng)求獲取到的赂蕴,是一個(gè) requests.models.Response 對(duì)象。通過(guò)這個(gè)對(duì)象可以很方便的獲取響應(yīng)的內(nèi)容(包括狀態(tài)碼舶胀、數(shù)據(jù)概说、響應(yīng)頭、響應(yīng)cookies等等)嚣伐。
2.1 響應(yīng)數(shù)據(jù)
通過(guò) Response 對(duì)象的 text 屬性可以獲得字符串格式的響應(yīng)內(nèi)容糖赔。
import requests
resp = requests.get('https://www.baidu.com')
resp.text
Requests 會(huì)自動(dòng)的根據(jù)響應(yīng)的報(bào)頭來(lái)猜測(cè)網(wǎng)頁(yè)的編碼是什么,然后根據(jù)猜測(cè)的編碼來(lái)解碼網(wǎng)頁(yè)內(nèi)容纤控,基本上大部分的網(wǎng)頁(yè)都能夠正確的被解碼挂捻。而如果發(fā)現(xiàn) text 解碼不正確的時(shí)候,就需要手動(dòng)的去指定解碼的編碼格式船万。
import requests
resp = requests.get('https://www.baidu.com')
resp.encoding = 'utf-8' # 設(shè)置編碼
resp.text
如果需要獲得原始的二進(jìn)制數(shù)據(jù)刻撒,那么使用 content 屬性即可。
resp.content
如果訪問(wèn)之后獲得的數(shù)據(jù)是 JSON 格式的耿导,可以使用 json() 方法声怔,直接獲取轉(zhuǎn)換成字典格式的數(shù)據(jù)。
resp = requests.get('http://httpbin.org/get')
resp.json()
2.2 狀態(tài)碼
通過(guò) status_code 屬性獲取響應(yīng)的狀態(tài)碼
resp = requests.get('http://httpbin.org/get')
resp.status_code
2.3 響應(yīng)頭
通過(guò) headers 屬性獲取響應(yīng)的報(bào)頭
resp.headers
2.4 服務(wù)器返回的 cookies
通過(guò) cookies 屬性獲取服務(wù)器返回的 cookies
import requests
url = 'http://www.baidu.com'
resp = requests.get(url)
resp.cookies
輸出的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.4.1 把cookies轉(zhuǎn)換成字典
# 獲取登錄成功后的cookie信息
cookiejar = resp.cookies # 獲取cookies
# 把cookie轉(zhuǎn)換成字典
cookie = requests.utils.dict_from_cookiejar(cookiejar)
2.5 url
可以使用 url
屬性查看訪問(wèn)的 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 中醋火,實(shí)現(xiàn)了 Session(會(huì)話) 功能,當(dāng)我們使用 Session 時(shí)箱吕,能夠像瀏覽器一樣芥驳,在沒(méi)有關(guān)閉關(guān)閉瀏覽器時(shí),能夠保持住訪問(wèn)的狀態(tài)茬高。
這個(gè)功能常常被我們用于登陸之后的數(shù)據(jù)獲取兆旬,使我們不用再一次又一次的傳遞 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"
}
}
首先我們需要去生成一個(gè) Session 對(duì)象怎栽,然后用這個(gè) Session 對(duì)象來(lái)發(fā)起訪問(wèn)丽猬,發(fā)起訪問(wèn)的方法與正常的請(qǐng)求是一模一樣的。
同時(shí)熏瞄,需要注意的是脚祟,如果是我們?cè)?get() 方法中傳入 headers 和 cookies 等數(shù)據(jù),那么這些數(shù)據(jù)只在當(dāng)前這一次請(qǐng)求中有效强饮。如果你想要讓一個(gè) headers 在 Session 的整個(gè)生命周期內(nèi)都有效的話由桌,需要用以下的方式來(lái)進(jìn)行設(shè)置:
# 設(shè)置整個(gè)headers
session.headers = {
'user-agent': 'lemonban/0.0.1'
}
# 增加一條headers
session.headers.update({'x-test': 'true'})
4. token
待補(bǔ)充...