一、安装Requests库
使用Python + Requests方式进行接口测试会更加灵活,代码也易于维护和扩展。
1、在线安装方式
pip install requests
二、Requests发送请求与参数传递
1、定义请求样式
(1)、导入Requests库
import requests
(2)、发送GET请求
requests.get("http://oa.grid365.cn/oa/view")
(3)、发送POST请求
requests.post("http://oa.grid365.cn/oa/view")
(4)、发送DELETE请求
requests.delete("http://oa.grid365.cn/oa/view")
(5)、发送HEAD请求
requests.head("http://oa.grid365.cn/oa/view")
(6)、发送OPTIONS请求
requests.options("http://oa.grid365.cn/oa/view")
(7)、发送PUT请求
requests.put("http://oa.grid365.cn/oa/view")
2、发送GET请求
Requests库发送GET请求的方式特别简单,可以携带参数传递,也可以不携带参数传递。
import requests
response = requests.get("http://www.baidu.com")
print(response.url)
params关键字参数
import requests
response = requests.get("http://www.baidu.com/s?",params={'wd':'python'})
print(response.url)
3、发送Form表单
HTTP规定POST提交的数据必须放在消息主体中,但是协议并没有规定必须使用何种编码方式。服务器端通常是根据请求头中的Content-Type字段来获知请求中的消息主体是用何种方式进行编码,在对消息主体进行解析。常见的几种编码方式如下:
(1)、application/x-www-form-urlencoded:以Form表单形式提交数据;
(2)、application/json:以JSON字符串方式提交数据;
(3)、text/xml:以XML文档字符串方式提交数据;
(4)、multipart/form-data:上传文件;
import requests
payload = {
'user_id':'61000xxxx17467',
'password':'xxxx',
'Referer':"http://ilink.sxlib.org.cn/uhtxxxxA5%BF%E7%9C%81%E9%A6%86/281860286/30"
}
responses = requests.post(
'http://ilink.sxlib.org.cn/uhtbin/cgisirsi/aMxxxx5%BF%E7%9C%81%E9%A6%86/281860286/30',
data=payload,
headers={"Content-Type":"application/x-www-form-urlencoded"}
)
print(responses.text)
4、发送XML数据
import requests
url = "http://ws.webxml.com.cn/WebServices/WeatherWs.asmx"
payload = """<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<getSupportCityString xmlns="http://WebXml.com.cn/">
<theRegionCode>3114</theRegionCode>
</getSupportCityString>
</soap:Body>
</soap:Envelope>
"""
responses = requests.post(url=url,data=payload,headers={"Content-Type":"text/xml"})
print(responses.text)
返回结果数据正确:
5、发送JSON请求
import requests,json
url = "https://api.apiopen.top/videoCategoryDetails?id=14"
r = requests.post(url=url,headers={'Content-Type':'application/json'})
print(r.text)
三、处理Token
Token是服务端生成的一串字符串,当第一次登录后,服务器会签发一个Token,然后奖此Token返回给客户端,客户端拿到Token以后可以存储起来。
(暂时没有测试地址)
四、处理Cookie
比如登录JIRA:不登录时无法查看BUG单。
responses = requests.post(
url="https://t.3xxxwer.cn/login.jsp",
data={
'os_username':'wxxxa',
'os_password':'wxxx4...',
'referer':'https://txxxr.cn/login.jsp'
}
)
print(responses.cookies)
<RequestsCookieJar[<Cookie JSESSIONID=6864F8B0219CB5DD15C104CDE386F008 for.........
def login():
responses = requests.post(
url="https://t.365power.cn/login.jsp",
data={
'os_username':'wxxx,
'os_password':'wxxx4...',
'referer':'https://t.xxxxn/login.jsp'
}
)
return responses.cookies
def ViewBug():
r = requests.get(url='https://t.xxxxr.cn/issues/?jql=project%20%3D%20FMxxxx%20%3D%20Bug',
cookies= login())
return r.text
print(ViewBug())
五、处理Session
Session表示会话对象。
(后续补充)
六、处理超时等待
接口响应时间较长时,可以用timeout设置超时时间。在指定时间内,接口未响应,此时就会抛出requests.exceptions.ConnectTimeout异常。
r = requests.get(url="http://www.baidu.com",timeout=0.001)
print(r.text)
七、Response对象解析
status_code:响应状态码;
raw:原始响应体;
content:字节方式的响应体;
text:字符串方式的响应体;
headers:以字典对象存储服务器响应头;
json:内置的JSON解码器,将响应结果转换为JSON字符串;
raise_for_status():失败请求(非200响应)抛出异常;
八、Requests文件上传
(暂时未有测试地址)
九、Requests常见异常
遇到网络问题(如DNS查询失败、拒绝连接等)时,Requests会抛出一个ConnectionError异常;
如果HTTP请求返回失败状态码,则Response.raise_for_status()会抛出一个HTTPError异常;
如果请求超时,则抛出一个Timeout异常;
如果请求超过了设定的最大重定向次数,则会抛出一个TooManyRedirects异常;
所有Requests显式抛出的异常都继承自requests.exceptions.RequestException类;
十、序列化和反序列化
序列化可以理解为把Python的对象编码转换成JSON格式的字符串,反序列化可以理解为把JSON格式的字符串解码为Python数据对象。在Python标准库中,提供了JSON库和pickle库来处理序列化和反序列化。
JSON是JS对象的字符串表示法,使用文本表示一个JS对象的信息,本质是一个字符串。JSON最常用的格式是对象的键值对。
JSON示例如下:
{
"code":200,
"msg":"success",
"newslist":[
{
"prov":"北京",
"p0":"6.25",
"p89":"5.32",
"p92":"6.59",
"p95":"7.01",
"p98":"7.99",
"time":"2021-03-10 07:02:00.429"
}
]
}
JSON库中提供的dumps()方法和loads()方法可以实现数据的系列化和反序列化。dumps()方法可以将JSON格式数据转化为Python的相关数据类型(如列表、元组、字典等);loads()方法是把Python数据类型转换为JSON相应的数据类型。
(1)、导入JSON库,查看JSON库中的方法:
import json
print(json.__all__)
['dump', 'dumps', 'load', 'loads', 'JSONDecoder', 'JSONDecodeError', 'JSONEncoder']
(2)、对Python中的字段进行序列化操作:
import json
dict1 = {'name':'fighter','age':27,'adress':'shannxi'}
print("未序列化之前的数据类型",type(dict1))
print("未序列化之前的数据",dict1)
str1 = json.dumps(dict1)
print("序列化之后的数据类型",type(str1))
print("序列化之后的数据",str1)
未序列化之前的数据类型 <class 'dict'>
未序列化之前的数据 {'name': 'fighter', 'age': 27, 'adress': 'shannxi'}
序列化之后的数据类型 <class 'str'>
序列化之后的数据 {"name": "fighter", "age": 27, "adress": "shannxi"}
(3)、对序列化后的JSON对象进行反序列化操作:
import json
dict1 = {'name':'fighter','age':27,'adress':'shannxi'}
print("未序列化之前的数据类型",type(dict1))
print("未序列化之前的数据",dict1)
str1 = json.dumps(dict1)
print("序列化之后的数据类型",type(str1))
print("序列化之后的数据",str1)
dict2 = json.loads(str1)
print("反序列化之后的数据类型",type(dict2))
print("反序列化之后的数据",dict2)
未序列化之前的数据类型 <class 'dict'>
未序列化之前的数据 {'name': 'fighter', 'age': 27, 'adress': 'shannxi'}
序列化之后的数据类型 <class 'str'>
序列化之后的数据 {"name": "fighter", "age": 27, "adress": "shannxi"}
反序列化之后的数据类型 <class 'dict'>
反序列化之后的数据 {'name': 'fighter', 'age': 27, 'adress': 'shannxi'}
十一、XML与JSON数据之间的转换
XML与JSON数据之间的转换需要用到xmltodict库。
直接安装:pip install xmltodict
import json
import xmltodict
def xmltojson(xmlstr):
xmlparse = xmltodict.parse(xmlstr)
jsonstr = json.dumps(xmlparse,indent=2,sort_keys=True)
print(jsonstr)
if __name__ == '__main__':
xmlinfo = """
<td class="rootbarcell">
<!-- Copyright (c) 1996 - 2008, SirsiDynix - Gateway Root Bar. -->
<!-- display text with CSS instead -->
<a href="/uhtbin/cgisirsi/ec9iNvwNbI/陕西省馆/110890096/38/1/X/BLASTOFF" class="rootbar">
查询首页</a>
<a href="/uhtbin/cgisirsi/3e5yKY1hqI/陕西省馆/110890096/1/26/X/BLASTOFF" class="rootbar">
主题导览</a>
<a href="/uhtbin/cgisirsi/iJNFUvSY8v/陕西省馆/110890096/1/446/X/BLASTOFF" class="rootbar">
新书推荐</a>
<a href="/uhtbin/cgisirsi/SG07BT71dp/陕西省馆/110890096/1/452/X/BLASTOFF" class="rootbar">
知识网关</a>
</td>
"""
xmltojson(xmlinfo)
parse()方法是XML提供的解析器,dumps(xmlparse,indent=2,sort_keys=True)用来将dici格式转成JSON格式。indent=2表示输出的JSON格式缩进两个空格,起到美化作用;sort_keys=True表示输出结果中JSON键按照ASCII码排序显示。转换后结果如下:
{
"td": {
"@class": "rootbarcell",
"a": [
{
"#text": "\u67e5\u8be2\u9996\u9875",
"@class": "rootbar",
"@href": "/uhtbin/cgisirsi/ec9iNvwNbI/\u9655\u897f\u7701\u9986/110890096/38/1/X/BLASTOFF"
},
{
"#text": "\u4e3b\u9898\u5bfc\u89c8",
"@class": "rootbar",
"@href": "/uhtbin/cgisirsi/3e5yKY1hqI/\u9655\u897f\u7701\u9986/110890096/1/26/X/BLASTOFF"
},
{
"#text": "\u65b0\u4e66\u63a8\u8350",
"@class": "rootbar",
"@href": "/uhtbin/cgisirsi/iJNFUvSY8v/\u9655\u897f\u7701\u9986/110890096/1/446/X/BLASTOFF"
},
{
"#text": "\u77e5\u8bc6\u7f51\u5173",
"@class": "rootbar",
"@href": "/uhtbin/cgisirsi/SG07BT71dp/\u9655\u897f\u7701\u9986/110890096/1/452/X/BLASTOFF"
}
]
}
}
JSON 数据转换为XML数据:
import xmltodict
def jsontoxml(jsonstr):
xmlstr = xmltodict.unparse(jsonstr)
print(xmlstr)
if __name__ == '__main__':
json ={"cnblogs":
{
'title':
{
'name':'fighter006',
'adress':'https://www.cnblogs.com/fighter006'
},
'info':
{
'page':'230',
'updated':'everyweekend'
},
'job':'tester'
}
}
jsontoxml(json)
<?xml version="1.0" encoding="utf-8"?>
<cnblogs><title><name>fighter006</name><adress>https://www.cnblogs.com/fighter006</adress></title><info><page>230</page><updated>everyweekend</updated></info><job>tester</job></cnblogs>