python测试之道>第5章>模拟网络请求

  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测试之道》——杨燕林、朱对洲、石赟 编著,如有侵权请联系删除。

相关文章
相关标签/搜索