python测试之道第5章模拟网络请求
python發(fā)送網(wǎng)絡(luò)請(qǐng)求是通過(guò)模塊中的方法來(lái)實(shí)現(xiàn)的,模塊定義好了請(qǐng)求的語(yǔ)法格式,只需要按照相應(yīng)的語(yǔ)法格式對(duì)號(hào)入座寫(xiě)代碼即可。
一般來(lái)說(shuō)我們測(cè)試的都是基于HTTP和HTTPS的網(wǎng)絡(luò)請(qǐng)求,python有很多自動(dòng)帶的原生模塊和擴(kuò)展模塊均可以模擬網(wǎng)絡(luò)請(qǐng)求。當(dāng)然我們?cè)趯?shí)際工作中會(huì)遇到很多其他協(xié)議請(qǐng)求,如WebSocket等。
本章以HTTP協(xié)議為例,采用原生模塊和擴(kuò)展模塊對(duì)比的方式,給大家剖析一下原理。原理性的東西雖然廣泛不被重視,但它對(duì)大家之后的學(xué)習(xí)是十分有好處的。
5.1?發(fā)送HTTP請(qǐng)求
5.1.1? requests模塊
python有很多模塊都可以發(fā)送HTTP請(qǐng)求,包括原生的模塊http.client,urlib2等,第三方模塊requests等,都封裝了發(fā)送HTTP請(qǐng)求的方法。由于原生的模塊過(guò)于復(fù)雜,不推薦使用,之后所有的請(qǐng)求都是基于第三方模塊requests進(jìn)行的,該模塊的好處在于簡(jiǎn)單,把請(qǐng)求的框架都搭建好了,只需要填入相應(yīng)的參數(shù)數(shù)據(jù),就能發(fā)送網(wǎng)絡(luò)請(qǐng)求了。
requests模塊非原生模塊,所有要使用還需要先進(jìn)行安裝,按照之前安裝模塊的方法,打開(kāi)命令行(在運(yùn)行中輸入cmd),然后在命令行輸入:
pip install requests
接前就會(huì)自動(dòng)安裝requests模塊及其相關(guān)模塊,然后就可以引入該模塊使用其提供的方法了。
import requests
后面會(huì)通過(guò)一些實(shí)例來(lái)介紹requests的具體使用方法。
?
5.1.2? 請(qǐng)求與響應(yīng)
HTTP就是發(fā)送請(qǐng)求和獲取響應(yīng)的一個(gè)過(guò)程,而requests模塊只需要一步就能完成這樣的一個(gè)過(guò)程,并且request支持所有的HTTP請(qǐng)求的方法和響應(yīng)數(shù)據(jù),先進(jìn)行語(yǔ)法介紹:
r = requests.方法(url, headers, data, ...)
其中url參數(shù)為必填的,畢竟HTTP請(qǐng)求就是對(duì)指定的URL進(jìn)行發(fā)送,其他各種參數(shù)可根據(jù)實(shí)際請(qǐng)求的需要選擇性使用。
發(fā)送請(qǐng)求后會(huì)獲取響應(yīng)結(jié)果,然后把結(jié)果賦值給變量,最后通過(guò)變量的屬性值取出需要的結(jié)果,下面就是常用返回結(jié)果:
r.headers 獲取返回的頭信息
r.text 獲取返回的主體(其實(shí)就是網(wǎng)頁(yè)html)
r.cookies 獲取返回的cookies
r.status_code 獲取返回的狀態(tài)碼(通常會(huì)通過(guò)狀態(tài)碼判斷請(qǐng)求是否成功)
學(xué)會(huì)requests的請(qǐng)求方法和獲取響應(yīng)的結(jié)果,就可以開(kāi)始網(wǎng)絡(luò)請(qǐng)求的測(cè)試了,下面就通過(guò)代碼實(shí)例來(lái)熟悉requests的模塊吧。
?
5.1.3? 請(qǐng)求參數(shù)
1.URL參數(shù)
URL是唯一的必填參數(shù),既然是網(wǎng)絡(luò)請(qǐng)求,必須要有URL地址才能發(fā)送,就像快遞一定要寫(xiě)目的地才能發(fā)件一樣。先從最簡(jiǎn)單的HTTP請(qǐng)求講起,請(qǐng)求一個(gè)靜態(tài)頁(yè)面,比如訪問(wèn)網(wǎng)易首頁(yè),通過(guò)抓包可以看到該請(qǐng)求是用的get方式發(fā)送的,所有要調(diào)用requests的get()方法來(lái)發(fā)送請(qǐng)求。
以網(wǎng)易首頁(yè)作為請(qǐng)求例子,實(shí)例代碼:
import requests #?導(dǎo)入requests模塊;
test_url = "http://www.163.com" #?定義url
response = requests.get(test_rul) #?實(shí)例化requests.get()方法
print(response.status_code) #?輸出返回的狀態(tài)碼
print(response.headers) #?輸出返回的頭信息
print(response.text) #?輸出返回的主體
代碼說(shuō)明:
1?導(dǎo)入requests模塊;
2 將網(wǎng)易首頁(yè)的URL賦值到變量test_url中(這樣的好處在于看起來(lái)清晰,也方便代碼今后的維護(hù));
3 在get()方法中將變量test_url直接傳入,即完成了帶URL的get請(qǐng)求(結(jié)果會(huì)賦值到變量reponse中,reponse中包含了返回結(jié)果的所有數(shù)據(jù),可以根據(jù)需要獲取想要的數(shù)據(jù));
4、5、6?獲取并打印返回的結(jié)果(狀態(tài)碼、頭信息、主體)
運(yùn)行結(jié)果如下圖:
可以看出通過(guò)requests發(fā)送的HTTP請(qǐng)求只有3行代碼,就那么簡(jiǎn)單的一行代碼完成整個(gè)請(qǐng)求。
整個(gè)請(qǐng)求過(guò)程全被封裝在方法之中,對(duì)于沒(méi)有編碼基礎(chǔ)的測(cè)試人員來(lái)說(shuō)再適合不過(guò)了。
?
2、headers? 參數(shù)
headers是最常用的參數(shù)之一,前面那個(gè)例子只是最簡(jiǎn)單的請(qǐng)求,沒(méi)有帶其他參數(shù)信息,而很多時(shí)候需要帶入headers發(fā)送請(qǐng)求,才可以獲取相應(yīng)的請(qǐng)求結(jié)果。
還是以網(wǎng)易首頁(yè)作為例子,如果是pc端的請(qǐng)求,會(huì)返回pc端的頁(yè),如果是手機(jī)端的請(qǐng)求,則返回手機(jī)端的頁(yè)面,這時(shí)候就要帶上headers參數(shù)的請(qǐng)求,通過(guò)瀏覽器的抓包工具可以看到headers有個(gè)字段“User-Agent",而服務(wù)器就是根據(jù)這個(gè)字段來(lái)判斷訪問(wèn)的來(lái)源,如果需要模擬手機(jī)端請(qǐng)求,需要將“User-Agent"改為請(qǐng)求的手機(jī)型號(hào)。
實(shí)例代碼:
import requeststest_url = "http://www.163.com"
h = {"User-Agent":"Android/H60-L01/4.4.2"} # 將headers賦值到變量h中;
reponse = requests.get(test_url, headers=h) # 在get()方法中加一個(gè)headers參數(shù),然后將變量賦值給headers參數(shù)。
print(reponse.status_code)
print(reponse.headers)
print(reponse.text)
?
運(yùn)行結(jié)果如下:
?
3、cookies? 參數(shù)
cookies也是最常用的參數(shù)之一,因?yàn)橹灰婕暗卿浐髷?shù)據(jù)獲取,都需要用到cookies參數(shù),那么如何獲取到cookies呢,一種是通過(guò)post發(fā)送登錄請(qǐng)求,獲取返回值的cookies屬性(這個(gè)會(huì)在后面的實(shí)例中講解),還有一種就是通過(guò)瀏覽器的網(wǎng)絡(luò)抓包方式獲取,在還不會(huì)熟練使用request模塊的前提下,就先介紹如何通過(guò)抓包獲取cookies。
首先打開(kāi)chrome瀏覽器,然后登錄網(wǎng)易郵箱(或其它網(wǎng)站),接著按F12(或在網(wǎng)頁(yè)右鍵,選擇檢查)打開(kāi)開(kāi)發(fā)者工具,抓取cookies的界面如下圖:
選擇application中的cookies,點(diǎn)擊對(duì)應(yīng)的測(cè)試URL域名,再找到session屬性并且domain是對(duì)應(yīng)測(cè)試請(qǐng)求的域名,然后這條信息name和value對(duì)應(yīng)的就是cookies了。
cookies參數(shù)以字典的形式發(fā)送,只需要對(duì)應(yīng)的將name和value傳入即可。
實(shí)例代碼:
import requestsc = {"JSESSIONID":"abcRPAFmBY_sqf2qRMmxw"}
test_url = "https://www.163.com/"
reponse = requests.get(test_url, cookies=c)
print(reponse.status_code)
print(reponse.headers)
print(reponse.text)
代碼說(shuō)明:
2 將瀏覽器抓取的cookies信息以字典的形式賦值到變量c之中;
4?在get方法中加一個(gè)cookies參數(shù),然后將變量c賦值給cookies參數(shù),即完成了帶著cookies信息的get請(qǐng)求。
其實(shí)cookies也是可以通過(guò)headers參數(shù)傳遞的,只是不同之處在于cookies是以字典的形式發(fā)送的,而在headers之中cookies只是其中一個(gè)鍵,所以需要把cookies放到該鍵對(duì)應(yīng)的值里面,而對(duì)應(yīng)的值是以key=value的形式傳入的,改一下代碼。
import requestsc = {"JSESSIONID":"abcRPAFmBY_sqf2qRMmxw"}
test_url = "https://www.163.com/"
reponse = requests.get(test_url, headers={"cookies":c}) # 此處cookies是作為headers的鍵值傳入;
print(reponse.status_code)
print(reponse.headers)
print(reponse.text)
代碼說(shuō)明:
4?在get方法中將變量c賦值給headers參數(shù)中的cookies字段,即完成了帶著cookies信息的get請(qǐng)求。
以上的兩種方法,推薦使用cookies參數(shù),一方面把cookies單獨(dú)分離出來(lái),不用與其他headers的字段放在一起,讓代碼更清晰,另一方面通過(guò)post請(qǐng)求返回的cookies是可以直接賦值到cookies參數(shù)之中,不需要再做轉(zhuǎn)換。
?
4、params?參數(shù)
對(duì)于params參數(shù)可以存放請(qǐng)求的表單,并會(huì)以key1=value1&key2=value2&key3=value3的形式跟進(jìn)URL之后發(fā)送,為了區(qū)分URL和參數(shù),最好不要把表單放在URL之中,可以通過(guò)params參數(shù)進(jìn)行發(fā)送,?上面網(wǎng)易郵箱的URL也是帶著參數(shù)的,直接放在URL之中,如果使用params參數(shù)就可以把后面的參數(shù)和URL分離。
還是以博客園登錄界面為例,只是URL部分把參數(shù)進(jìn)行分離,代碼如下:
import requests# test_url = "https://passport.cnblogs.com/user/signin?ReturnUrl=https%3A%2F%2Fwww.cnblogs.com%2F"
test_url = "https://passport.cnblogs.com/user/signin"
p = {"ReturnUrl":"https%3A%2F%2Fwww.cnblogs.com%2F"}
reponse = requests.get(test_url, params=p)
print(reponse.status_code)
print(reponse.headers)
print(reponse.text)
代碼說(shuō)明:
4?將需要發(fā)送表單以字典的形式賦值到變量p之中。
5?在get方法中加一個(gè)params的參數(shù),然后將變量p賦值給params參數(shù),即完成了帶著params信息的get請(qǐng)求。
如果不使用params參數(shù),也可以直接把表單加在URL中,只是代碼不清晰,所以不推薦直接把表單加在URL中。
?
5、data 參數(shù)
data參數(shù)也是用于存放請(qǐng)求表單,是request模塊中最重要的參數(shù)之一。
在使用data之前,先來(lái)了解一下post提交數(shù)據(jù)類型,區(qū)別與params,params只有一種類型(字符串類型),而post可以提交4種類型的數(shù)據(jù),至于需要提交什么類型的數(shù)據(jù),取決于服務(wù)器接收的數(shù)據(jù)類型。post的數(shù)據(jù)類型需要和服務(wù)器接收的一致,不然服務(wù)器就無(wú)法正常識(shí)別post的數(shù)據(jù),導(dǎo)致測(cè)試結(jié)果報(bào)錯(cuò)。就像協(xié)議一樣,接收方預(yù)定接收哪種類型的表單,然后發(fā)頭方按照接收方指定的協(xié)議發(fā)送表單,這樣就完成了一個(gè)表單的提交。
如何識(shí)別服務(wù)器接收的數(shù)據(jù)類型?最簡(jiǎn)單的方式還是抓包。抓取數(shù)據(jù)類型的界面如下:
通過(guò)抓包可以看到,在request headers?中有一個(gè)content-type的字段,這個(gè)字段表示了post發(fā)送數(shù)據(jù)的類型,一般分為以下4種類型:
第1種:content-type:application/json
實(shí)際上,現(xiàn)在越來(lái)越多的人反application/json作為請(qǐng)求頭,用來(lái)告訴服務(wù)器消息主體是序列化后的json字符串。由于json規(guī)范流行,除了低版本IE之外的各大瀏覽器都原生支持json.stringify,服務(wù)器端語(yǔ)言也都有處理json的函數(shù),并且json格式支持比鍵值對(duì)更加復(fù)雜的結(jié)果化數(shù)據(jù)。
第2種:content-type:application/x-www-form-urlencoded
這是最常見(jiàn)的post提交數(shù)據(jù)的方式,瀏覽器的原生form表單,如果不設(shè)置enctype屬性,那么最終就會(huì)以application/x-www-form-urlencoded方式提交數(shù)據(jù)。提交的數(shù)據(jù)按照key1=value1&key2=value2的方式進(jìn)行編碼,key和value都進(jìn)行了URL轉(zhuǎn)碼,然后打包發(fā)送到服務(wù)器。
?
第3種:content-type:multipart/form-data
content-type為multipart/form-data方式,主要用于上傳文件。需要注意的是同時(shí)form的enctype屬性也要設(shè)置為multipart/form-data,才能正確提交并解析所傳輸?shù)臄?shù)據(jù)。
?
第4種:content-type:text/xml
? 它是一種使用http作為傳輸協(xié)議,XML作為編碼方式的遠(yuǎn)程調(diào)用規(guī)范。考慮到XML結(jié)構(gòu)還是過(guò)于臃腫,一般場(chǎng)景用json會(huì)更靈活方便,所以這種提交我們的工作中實(shí)際使用的不多,僅了解一下就可以了。
?
最常見(jiàn)的是 第2種?類型,直接將數(shù)據(jù)以{key:value}的字典形式賦值給表單,然后通過(guò)request.post()中的data參數(shù)傳遞就可以了。
以網(wǎng)易音樂(lè)為例,搜索一首歌曲,通過(guò)抓包可以看到content-type是application/x-www-form-urlencoded,網(wǎng)易音樂(lè)的數(shù)據(jù)類型抓取圖如下:
搜索一首”一次就好“,通過(guò)抓包會(huì)發(fā)現(xiàn)有進(jìn)行加密,那就直接把加密后的內(nèi)容放到form之中發(fā)送出去,網(wǎng)易音樂(lè)的表單抓取如下圖:
?
?
實(shí)例代碼:
import requeststest_url = "https://music.163.com/weapi/search/suggest/web?csrf_token="
f = {"params":"ShQVLipkE8Y/p89iMoKOX5whEin1ZyoKeXZJJe+rBg+8mrEQT3RaAR5UP5B+ayoKrPIVzxsVuuFA1askCPcBzRJ6qOoPsPz06xStotZZGTmHrzaz1RcbiRpYOOrZl8NC",\
"encSecKey":"9ac26cbd1a87fd9790fb1cc2f0a475a5cd24be6b73e1b516f86b00ab58b568c0d4303eb6314bbedf5adedb968f047f44bb6ebe1fd9cfa09339a781d762e8aba0184c8a57dc53d1717f89d5c85d02e635cec9e7610fac4faac33838a3f299a1aa672390e4430b21ee2ea03e37aee53d17d70973933ffdf3fc7872101a9ff973da"\
}
reponse = requests.post(test_url, data=f)
print(reponse.status_code)
print(reponse.headers)
print(reponse.text)
? 代碼說(shuō)明:
3?將需要發(fā)送的表單以字典形式賦值到變量form之中。
4?在post方法中加一個(gè)data參數(shù),然后將變量賦值給data參數(shù),即完成了帶著表單信息的post請(qǐng)求。
運(yùn)行結(jié)果如下圖:
?
以上內(nèi)容來(lái)自《python測(cè)試之道》——楊燕林、朱對(duì)洲、石赟?編著,若有侵權(quán)請(qǐng)聯(lián)系刪除。
轉(zhuǎn)載于:https://www.cnblogs.com/liukang92/p/9634941.html
總結(jié)
以上是生活随笔為你收集整理的python测试之道第5章模拟网络请求的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: ubuntu搭建tiny4412环境【学
- 下一篇: Attaching to process