成长很苦,进步很甜,希望我们大家每天都能够向上生长。
本文转载自https://sutune.me/2018/07/18/requests/
request相关类封装系本人封装
概述
前面我们介绍了接口测试工具:Postman和Jmeter。利用接口测试工具上手使用虽然容易,但是还是不够灵活。例如需要界面上各种配置,有时还需限定的语言脚本来辅助(Postman限定使用Js
,Jmeter限定使用Java
)
因此,如果我们直接使用自己熟悉的语言编写代码来进行接口测试将会更加灵活方便,这里我们将使用Python来进行接口测试。
Requests
进行接口测试需要发送HTTP请求,Python最基础的 HTTP 库有 Urllib、Httplib2、Requests、Treq 等,这里我们推荐使用Requests
库来进行接口测试。
Requests 基于 urllib,采用 Apache2 Licensed 开源协议的 HTTP 库。它比 urllib 更加方便,可以节约我们大量的工作,完全满足 HTTP 测试需求。目前很多Python爬虫也使用Requests
库。
官方文档摘要
Requests 口号为:“让 HTTP 服务人类”
Requests 唯一的一个非转基因的 Python HTTP 库,人类可以安全享用。
警告:非专业使用其他 HTTP 库会导致危险的副作用,包括:安全缺陷症、冗余代码症、重新发明轮子症、啃文档症、抑郁、头疼、甚至死亡。
用户见证
Twitter、Spotify、Microsoft、Amazon、Lyft、BuzzFeed、Reddit、NSA、女王殿下的政府、Amazon、Google、Twilio、Mozilla、Heroku、PayPal、NPR、Obama for America、Transifex、Native Instruments、Washington Post、Twitter、SoundCloud、Kippt、Readability、以及若干不愿公开身份的联邦政府机构都在内部使用。
功能特性
- Keep-Alive & 连接池
- 国际化域名和 URL
- 带持久 Cookie 的会话
- 浏览器式的 SSL 认证
- 自动内容解码
- 基本/摘要式的身份认证
- 优雅的 key/value Cookie
- 自动解压
- Unicode 响应体
- HTTP(S) 代理支持
- 文件分块上传
- 流下载
- 连接超时
- 分块请求
- 支持 .netrc(用户配置脚本文件)
Requests安装
使用pip安装命令如下:
1 | pip install requests |
安装检测
打开cmd窗口,输入python
然后导入requests
如果安装成功没有任何提示
1 | import requests |
如果提示如下内容则说明安装失败
1 | ImportError: No module named 'requests' |
如果没有安装pip的参考:Python 安装与配置
Requests 基础应用
发送不同类型HTTP请求
requests库内置了不同的方法来发送不同类型的http请求,用法如下所示:
requestbasic.py
1 | import requests |
执行结果,200
是状态码表示发送请求成功。
1 | 200 |
参数传递
传递URL参数
一般在GET请求中我们使用查询字符串(query string)来进行参数传递,在requests库中使用方法如下:
requestbasic.py
1 | import requests |
执行结果
1 | C:Python35python.exe D:/apitest/requestsapi_test/params.py |
传递body参数
在Post请求中,一般参数都在请求体(Request body)中传递,在Requests中用法如下:
1 | formdata = {'user': 'zxw', 'passwd': '8888'} |
执行结果:
1 | { |
请求头定制
如果你想为请求添加 HTTP 头部,只要简单地传递一个 dict
给 headers
参数就可以了。
用法如下:
1 | formdata = {'user': 'zxw', 'passwd': '8888'} |
返回值
1 | { |
Tips:很多爬虫程序都会定制headers来避免被封,如下面爬取知乎页面元素就设置了请求头。
1 | headers={'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.181 Safari/537.36' |
响应内容
当请求发送成功之后,我们可以获取响应内容。如响应状态码,响应头信息、响应体内容。
1 | formdata = {'user': 'zxw', 'passwd': '8888'} |
返回结果
1 | 200 |
Requests 进阶应用
Cookie设置
设置cookie
通过cookies
参数可以设置Cookie
request_advance.py
1 | import requests |
运行结果:
1 | {"cookies":{"user":"51zxw"}} |
获取cookie
请求百度首页,然后获取cookie,实现如下:
1 | # 获取cookie |
运行结果:
1 | <class 'requests.cookies.RequestsCookieJar'> |
调用了 cookies 属性即可成功得到了 Cookies,可以发现它是一个 RequestCookieJar
类型,然后我们用 items()
方法将其转化为元组组成的列表,遍历输出每一个 Cookie 的名和值,实现 Cookies 的遍历解析。
超时
你可以让requests 在经过以 timeout
参数设定的秒数时间之后停止等待响应。防止某些请求没有响应而一直处于等待状态。
下面案例故意设置一个很小的超时时间,为了来看一下超时后的一个响应处理,但是实际测试过程中不要设置这短。
1 |
|
超时响应异常
1 | raise ConnectTimeout(e, request=request) |
文件上传
Reqeuests 可以使用参数files
模拟提交一些文件数据,假如有的接口需要我们上传文件,我们同样可以利用它来上传,实现非常简单,实例如下:
1 | #上传文件 |
会话对象
会话(Session)
在计算机中,尤其是在网络应用中,称为“会话控制”。Session
对象存储特定用户会话所需的属性及配置信息。这样,当用户在应用程序的 Web 页之间跳转时,存储在 Session 对象中的变量将不会丢失,而是在整个用户会话中一直存在下去。
比如你先进行了登录操作,然后打开个人中心详情页面,个人中心详情页面如何知道展示的是刚刚登录的这个用户的信息,那么这里就需要使用Session
来存储相关信息。
在接口测试过程中接口之间经常有依赖关系,比如下面这两个请求一个是设置Cookie
,另外一个是获取cookie
,在没有Session
保存机制的情况下,第二个接口无法获取第一个接口设置的Cookie
值。
1 | #设置cookie |
响应数据
1 | { |
Request的会话对象让你能够跨请求保持某些参数。它也会在同一个 Session 实例发出的所有请求之间保持 cookie。具体使用如下:
1 | #生成会话对象 |
运行结果
1 | { |
所以,利用 Session 我们可以做到模拟同一个会话,而且不用担心 Cookies 的问题,通常用于模拟登录成功之后再进行下一步的操作。
SSL证书验证
Requests 可以为 HTTPS 请求验证 SSL 证书,就像 web 浏览器一样。SSL 验证默认是开启的,如果证书验证失败,Requests 会抛出 SSLError:
如果不想验证SSL则可以使用verify
参数关闭验证SSL。
下面是验证12306网站的证书。
1 | r=requests.get('https://www.12306.cn') |
运行结果:
1 | raise SSLError(e, request=request) |
Tips:12306的证书是自己颁发给自己的,所以会出现认证失败。
代理设置
代理简介
代理(Proxy),也称网络代理,是一种特殊的网络服务,允许一个网络终端(一般为客户端)通过这个服务与另一个网络终端(一般为服务器)进行非直接的连接。
代理服务器位于客户端和访问互联网之间,服务器接收客户端的请求,然后代替客户端向目标网站发出请求,所有的流量路由均来自代理服务器的IP地址,从而获取到一些不能直接获取的资源。
对于有些接口,在测试的时候请求几次,能正常获取内容。但是一旦开始大规模频繁请求(如性能测试)服务器可能会开启验证,甚至直接把IP给封禁掉。
那么为了防止这种情况的发生,我们就需要设置代理来解决这个问题,在 Requests 中需要用到 proxies
这个参数,在爬虫中会常用到代理。
1 | #代理设置 |
运行结果如下:可以看到origin
参数即为我们设置的代理ip
1 | { |
身份认证
很多接口都需要身份认证,Requests支持多种身份认证,具体使用方法如下:
下面案例主要验证了2种身份类型:BasicAuth
和 digestAuth
1 | from requests.auth import HTTPBasicAuth |
运行结果:
1 | {"authenticated":true,"user":"51zxw"} |
流式请求
有一些接口返回值比较特殊,不是单纯返回一个结果,而是多个结果,比如某个查询接口,返回值为排行榜前10的商品信息。
实践案例
请求接口如下:
1 | http://httpbin.org/stream/{num} |
num
表示返回结果集的数量,比如输入10
则会返回10个下面这种不同id的结果
1 | {"url": "http://httpbin.org/stream/10", "args": {}, "headers": {"Host": "httpbin.org", "Connection": "close", "Accept": "application/json", "User-Agent": "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.98 Safari/537.36 LBBROWSER", "Referer": "http://httpbin.org/", "Accept-Encoding": "gzip, deflate, sdch", "Accept-Language": "zh-CN,zh;q=0.8", "Cookie": "gaugesuniquehour=1; gaugesuniqueday=1; gaugesuniquemonth=1; gaugesuniqueyear=1; gaugesunique=1"}, "origin": "110.52.4.234", "id": 0} |
针对这种类型的接口我们对结果集的处理需要使用迭代方法iter_lines()
来处理,具体使用如下:
1 | import json |
返回结果:
1 | 0 |
request相关类封装
class MyRequests:
"""
对request请求进行封装
"""
def __init__(self):
""""创建请求会话"""
self.my_session = requests.Session()
def __call__(self, url, methmod="post", data=None, is_json=True, **kwargs,):
# 因对外接口方式全部为post,默认给post,对于其他方式直接在post方法后进行拓展即可
methmod = methmod.lower()
if isinstance(data, str):
try:
data = json.loads(data)
except Exception as e:
print(e)
data = eval(data)
if methmod == "post":
# 对于只需要header中token鉴权方式的接口可以省略这一步传参
header = self.header if hasattr(MyRequests, 'header') else None
if is_json:
res = self.my_session.request(methmod, url, headers=header, json=data, **kwargs)
else:
res = self.my_session.request(methmod, url, headers=header, data=data, **kwargs)
else:
res = None
print("不支持{}的请求方法".format(methmod))
return res.json()
def close(self):
return self.my_session.close()
本文由博客一文多发平台 OpenWrite 发布!