python发送网络请求是经过模块中的方法来实现的,模块定义好了请求的语法格式,只须要按照相应的语法格式对号入座写代码便可。html
通常来讲咱们测试的都是基于HTTP和HTTPS的网络请求,python有不少自动带的原生模块和扩展模块都可以模拟网络请求。固然咱们在实际工做中会遇到不少其余协议请求,如WebSocket等。python
本章以HTTP协议为例,采用原生模块和扩展模块对比的方式,给你们剖析一下原理。原理性的东西虽然普遍不被重视,但它对你们以后的学习是十分有好处的。web
5.1 发送HTTP请求chrome
5.1.1 requests模块json
python有不少模块均可以发送HTTP请求,包括原生的模块http.client,urlib2等,第三方模块requests等,都封装了发送HTTP请求的方法。因为原生的模块过于复杂,不推荐使用,以后全部的请求都是基于第三方模块requests进行的,该模块的好处在于简单,把请求的框架都搭建好了,只须要填入相应的参数数据,就能发送网络请求了。api
requests模块非原生模块,全部要使用还须要先进行安装,按照以前安装模块的方法,打开命令行(在运行中输入cmd),而后在命令行输入:浏览器
pip install requests服务器
接前就会自动安装requests模块及其相关模块,而后就能够引入该模块使用其提供的方法了。cookie
import requests网络
后面会经过一些实例来介绍requests的具体使用方法。
5.1.2 请求与响应
HTTP就是发送请求和获取响应的一个过程,而requests模块只须要一步就能完成这样的一个过程,而且request支持全部的HTTP请求的方法和响应数据,先进行语法介绍:
r = requests.方法(url, headers, data, ...)
其中url参数为必填的,毕竟HTTP请求就是对指定的URL进行发送,其余各类参数可根据实际请求的须要选择性使用。
发送请求后会获取响应结果,而后把结果赋值给变量,最后经过变量的属性值取出须要的结果,下面就是经常使用返回结果:
r.headers 获取返回的头信息
r.text 获取返回的主体(其实就是网页html)
r.cookies 获取返回的cookies
r.status_code 获取返回的状态码(一般会经过状态码判断请求是否成功)
学会requests的请求方法和获取响应的结果,就能够开始网络请求的测试了,下面就经过代码实例来熟悉requests的模块吧。
5.1.3 请求参数
1.URL参数
URL是惟一的必填参数,既然是网络请求,必需要有URL地址才能发送,就像快递必定要写目的地才能发件同样。先从最简单的HTTP请求讲起,请求一个静态页面,好比访问网易首页,经过抓包能够看到该请求是用的get方式发送的,全部要调用requests的get()方法来发送请求。
以网易首页做为请求例子,实例代码:
import requests # 导入requests模块;
test_url = "http://www.163.com" # 定义url
response = requests.get(test_rul) # 实例化requests.get()方法
print(response.status_code) # 输出返回的状态码
print(response.headers) # 输出返回的头信息
print(response.text) # 输出返回的主体
代码说明:
1 导入requests模块;
2 将网易首页的URL赋值到变量test_url中(这样的好处在于看起来清晰,也方便代码从此的维护);
3 在get()方法中将变量test_url直接传入,即完成了带URL的get请求(结果会赋值到变量reponse中,reponse中包含了返回结果的全部数据,能够根据须要获取想要的数据);
四、五、6 获取并打印返回的结果(状态码、头信息、主体)
运行结果以下图:
能够看出经过requests发送的HTTP请求只有3行代码,就那么简单的一行代码完成整个请求。
整个请求过程全被封装在方法之中,对于没有编码基础的测试人员来讲再适合不过了。
二、headers 参数
headers是最经常使用的参数之一,前面那个例子只是最简单的请求,没有带其余参数信息,而不少时候须要带入headers发送请求,才能够获取相应的请求结果。
仍是以网易首页做为例子,若是是pc端的请求,会返回pc端的页,若是是手机端的请求,则返回手机端的页面,这时候就要带上headers参数的请求,经过浏览器的抓包工具能够看到headers有个字段“User-Agent",而服务器就是根据这个字段来判断访问的来源,若是须要模拟手机端请求,须要将“User-Agent"改成请求的手机型号。
实例代码:
import requests
test_url = "http://www.163.com"
h = {"User-Agent":"Android/H60-L01/4.4.2"} # 将headers赋值到变量h中;
reponse = requests.get(test_url, headers=h) # 在get()方法中加一个headers参数,而后将变量赋值给headers参数。
print(reponse.status_code)
print(reponse.headers)
print(reponse.text)
运行结果以下:
三、cookies 参数
cookies也是最经常使用的参数之一,由于只要涉及登陆后数据获取,都须要用到cookies参数,那么如何获取到cookies呢,一种是经过post发送登陆请求,获取返回值的cookies属性(这个会在后面的实例中讲解),还有一种就是经过浏览器的网络抓包方式获取,在还不会熟练使用request模块的前提下,就先介绍如何经过抓包获取cookies。
首先打开chrome浏览器,而后登陆网易邮箱(或其它网站),接着按F12(或在网页右键,选择检查)打开开发者工具,抓取cookies的界面以下图:
选择application中的cookies,点击对应的测试URL域名,再找到session属性而且domain是对应测试请求的域名,而后这条信息name和value对应的就是cookies了。
cookies参数以字典的形式发送,只须要对应的将name和value传入便可。
实例代码:
import requests
c = {"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)
代码说明:
2 将浏览器抓取的cookies信息以字典的形式赋值到变量c之中;
4 在get方法中加一个cookies参数,而后将变量c赋值给cookies参数,即完成了带着cookies信息的get请求。
其实cookies也是能够经过headers参数传递的,只是不一样之处在于cookies是以字典的形式发送的,而在headers之中cookies只是其中一个键,因此须要把cookies放到该键对应的值里面,而对应的值是以key=value的形式传入的,改一下代码。
import requests
c = {"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)
代码说明:
4 在get方法中将变量c赋值给headers参数中的cookies字段,即完成了带着cookies信息的get请求。
以上的两种方法,推荐使用cookies参数,一方面把cookies单独分离出来,不用与其余headers的字段放在一块儿,让代码更清晰,另外一方面经过post请求返回的cookies是能够直接赋值到cookies参数之中,不须要再作转换。
四、params 参数
对于params参数能够存放请求的表单,并会以key1=value1&key2=value2&key3=value3的形式跟进URL以后发送,为了区分URL和参数,最好不要把表单放在URL之中,能够经过params参数进行发送, 上面网易邮箱的URL也是带着参数的,直接放在URL之中,若是使用params参数就能够把后面的参数和URL分离。
仍是以博客园登陆界面为例,只是URL部分把参数进行分离,代码以下:
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)
代码说明:
4 将须要发送表单以字典的形式赋值到变量p之中。
5 在get方法中加一个params的参数,而后将变量p赋值给params参数,即完成了带着params信息的get请求。
若是不使用params参数,也能够直接把表单加在URL中,只是代码不清晰,因此不推荐直接把表单加在URL中。
五、data 参数
data参数也是用于存放请求表单,是request模块中最重要的参数之一。
在使用data以前,先来了解一下post提交数据类型,区别与params,params只有一种类型(字符串类型),而post能够提交4种类型的数据,至于须要提交什么类型的数据,取决于服务器接收的数据类型。post的数据类型须要和服务器接收的一致,否则服务器就没法正常识别post的数据,致使测试结果报错。就像协议同样,接收方预约接收哪一种类型的表单,而后发头方按照接收方指定的协议发送表单,这样就完成了一个表单的提交。
如何识别服务器接收的数据类型?最简单的方式仍是抓包。抓取数据类型的界面以下:
经过抓包能够看到,在request headers 中有一个content-type的字段,这个字段表示了post发送数据的类型,通常分为如下4种类型:
第1种:content-type:application/json
实际上,如今愈来愈多的人反application/json做为请求头,用来告诉服务器消息主体是序列化后的json字符串。因为json规范流行,除了低版本IE以外的各大浏览器都原生支持json.stringify,服务器端语言也都有处理json的函数,而且json格式支持比键值对更加复杂的结果化数据。
第2种:content-type:application/x-www-form-urlencoded
这是最多见的post提交数据的方式,浏览器的原生form表单,若是不设置enctype属性,那么最终就会以application/x-www-form-urlencoded方式提交数据。提交的数据按照key1=value1&key2=value2的方式进行编码,key和value都进行了URL转码,而后打包发送到服务器。
第3种:content-type:multipart/form-data
content-type为multipart/form-data方式,主要用于上传文件。须要注意的是同时form的enctype属性也要设置为multipart/form-data,才能正确提交并解析所传输的数据。
第4种:content-type:text/xml
它是一种使用http做为传输协议,XML做为编码方式的远程调用规范。考虑到XML结构仍是过于臃肿,通常场景用json会更灵活方便,因此这种提交咱们的工做中实际使用的很少,仅了解一下就能够了。
最多见的是 第2种 类型,直接将数据以{key:value}的字典形式赋值给表单,而后经过request.post()中的data参数传递就能够了。
以网易音乐为例,搜索一首歌曲,经过抓包能够看到content-type是application/x-www-form-urlencoded,网易音乐的数据类型抓取图以下:
搜索一首”一次就好“,经过抓包会发现有进行加密,那就直接把加密后的内容放到form之中发送出去,网易音乐的表单抓取以下图:
实例代码:
import requests
test_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)
代码说明:
3 将须要发送的表单以字典形式赋值到变量form之中。
4 在post方法中加一个data参数,而后将变量赋值给data参数,即完成了带着表单信息的post请求。
运行结果以下图:
以上内容来自《python测试之道》——杨燕林、朱对洲、石赟 编著,如有侵权请联系删除。