一、Post请求

1、使用python发送一个Post请求

有时候遇到请求url中有很多参数。

1.1 示例1

accounts和pwd请到http://shop-xo.hctestedu.com/注册。

import requests  # 请求体 data = { "accounts": "xx", "pwd": "xxx", "type": "username" } # 只有php项目需要application和application_client_type # 写法一, 在请求Url中带上所有参数,application和application_client_type,用&隔开 response = requests.post(url="http://shop-xo.hctestedu.com/index.php?" "s=api/user/login" "&application=app" "&applicaiton_client_type=weixin", json=data) # 输出响应结果 print(response.text) 

执行结果:

{"msg":"登录成功","code":0,"data":{"id":"7073","username":"xx","nickname":"","mobile":"","email":"","avatar":"http://shop-xo.hctestedu.com/static/index/default/images/default-user-avatar.jpg","alipay_openid":"","weixin_openid":"","weixin_unionid":"","weixin_web_openid":"","baidu_openid":"","toutiao_openid":"","qq_openid":"","qq_unionid":"","integral":"189","locking_integral":"0","referrer":"0","add_time":"1646195490","add_time_text":"2022-03-02 12:31:30","mobile_security":"","email_security":"","user_name_view":"xx","is_mandatory_bind_mobile":0,"token":"xxxxxx"}} 

1.2 示例2

使用不定长参数 params,将url中需要的参数单独封装。

import requests  # 请求体 data = { "accounts": "xx", "pwd": "xxx", "type": "username" } # 使用不定长参数params param_data = { "application": "app", "application_client_type": "weixin" } # 写法2:使用不定长参数params response = requests.post(url="http://shop-xo.hctestedu.com/index.php?" "s=api/user/login", params=param_data, json=data) # 输出响应结果 print(response.text) 

执行结果:

{"msg":"登录成功","code":0,"data":{"id":"22299","username":"xx","nickname":"","mobile":"","email":"","avatar":"http://shop-xo.hctestedu.com/static/index/default/images/default-user-avatar.jpg","alipay_openid":"","weixin_openid":"","weixin_unionid":"","weixin_web_openid":"","baidu_openid":"","toutiao_openid":"","qq_openid":"","qq_unionid":"","integral":"0","locking_integral":"0","referrer":"0","add_time":"1678005098","add_time_text":"2023-03-05 16:31:38","mobile_security":"","email_security":"","user_name_view":"xx","is_mandatory_bind_mobile":0,"token":"xxxxx"}} 

二、获取Response body

1、response.text

用type()查看response.text的类型,是str

import requests  # 请求体 data = { "accounts": "xx", "pwd": "xxx", "type": "username" } # 使用不定长参数params param_data = { "application": "app", "application_client_type": "weixin" } # 写法2:使用不定长参数params response = requests.post(url="http://shop-xo.hctestedu.com/index.php?" "s=api/user/login", params=param_data, json=data) # 输出响应结果 print(response.text) print(type(response.text)) 

执行结果:

{"msg":"登录成功","code":0,"data":{"id":"22299","username":"xx","nickname":"","mobile":"","email":"","avatar":"http://shop-xo.hctestedu.com/static/index/default/images/default-user-avatar.jpg","alipay_openid":"","weixin_openid":"","weixin_unionid":"","weixin_web_openid":"","baidu_openid":"","toutiao_openid":"","qq_openid":"","qq_unionid":"","integral":"0","locking_integral":"0","referrer":"0","add_time":"1678005098","add_time_text":"2023-03-05 16:31:38","mobile_security":"","email_security":"","user_name_view":"xx","is_mandatory_bind_mobile":0,"token":"xxxxx"}} <class 'str'> 

2、response.json()

用type()查看response.json()的类型,是dict

import requests  # 请求体 data = { "accounts": "xx", "pwd": "xxx", "type": "username" } # 使用不定长参数params param_data = { "application": "app", "application_client_type": "weixin" } # 写法2:使用不定长参数params response = requests.post(url="http://shop-xo.hctestedu.com/index.php?" "s=api/user/login", params=param_data, json=data) # 输出响应结果 print(response.json()) print(type(response.json())) 

执行结果:

{"msg":"登录成功","code":0,"data":{"id":"22299","username":"xx","nickname":"","mobile":"","email":"","avatar":"http://shop-xo.hctestedu.com/static/index/default/images/default-user-avatar.jpg","alipay_openid":"","weixin_openid":"","weixin_unionid":"","weixin_web_openid":"","baidu_openid":"","toutiao_openid":"","qq_openid":"","qq_unionid":"","integral":"0","locking_integral":"0","referrer":"0","add_time":"1678005098","add_time_text":"2023-03-05 16:31:38","mobile_security":"","email_security":"","user_name_view":"xx","is_mandatory_bind_mobile":0,"token":"xxxxx"}} <class 'dict'> 

三、获取响应状态码:res.status_code

print(response.status_code) 

执行结果:

200 

更多状态码:

状态代码有三位数字组成,第一个数字定义了响应的类别,共分五种类别: 1xx:指示信息--表示请求已接收,继续处理 2xx:成功--表示请求已被成功接收、理解、接受 3xx:重定向--要完成请求必须进行更进一步的操作 4xx:客户端错误--请求有语法错误或请求无法实现 5xx:服务器端错误--服务器未能实现合法的请求  常见状态码: 200 OK //客户端请求成功 400 Bad Request //客户端请求有语法错误,不能被服务器所理解 401 Unauthorized //请求未经授权,这个状态代码必须和WWW-Authenticate报头域一起使用 403 Forbidden //服务器收到请求,但是拒绝提供服务 404 Not Found //请求资源不存在,eg:输入了错误的URL 500 Internal Server Error //服务器发生不可预期的错误 503 Server Unavailable //服务器当前不能处理客户端的请求,一段时间后可能恢复正常 

四、获取响应cookies:res.cookies

print(response.cookies) 

执行结果:

<RequestsCookieJar[<Cookie PHPSESSID=92ppj01t00t4v142rd8fsmos7k for shop-xo.hctestedu.com/>]> 

五、获取响应headers:res.headers

print(response.headers) 

执行结果:

{'Server': 'nginx', 'Date': 'Sun, 05 Mar 2023 10:04:02 GMT', 'Content-Type': 'application/json; charset=utf-8', 'Transfer-Encoding': 'chunked', 'Connection': 'keep-alive', 'Set-Cookie': 'PHPSESSID=ul9qsgallg17d5am81q08pfhj0; path=/; HttpOnly', 'Expires': 'Thu, 19 Nov 1981 08:52:00 GMT', 'Cache-Control': 'no-store, no-cache, must-revalidate', 'Pragma': 'no-cache'}  

六、获取响应结果原始内容:res.content

content,没有经过编译的,以字节的形式展示。而上述提到的text是编译过的。自动找到请求头中的编码格式,进行解析。

print(response.content) print(type(response.content)) 

执行结果:

b'{"msg":"xe7x99xbbxe5xbdx95xe6x88x90xe5x8ax9f","code":0,"data":{"id":"22299","username":"xxxxx","nickname":"","mobile":"","email":"","avatar":"http:\/\/shop-xo.hctestedu.com\/static\/index\/default\/images\/default-user-avatar.jpg","alipay_openid":"","weixin_openid":"","weixin_unionid":"","weixin_web_openid":"","baidu_openid":"","toutiao_openid":"","qq_openid":"","qq_unionid":"","integral":"0","locking_integral":"0","referrer":"0","add_time":"1678005098","add_time_text":"2023-03-05 16:31:38","mobile_security":"","email_security":"","user_name_view":"xxxxx","is_mandatory_bind_mobile":0,"token":"d653d78ac417f65e1cd38c6f3e220341"}}' <class 'bytes'>  

content还支持手动的编码,例如使用utf-8编码,编码后的是str类型,json本质是一种字符串类型

resp = response.content.decode("utf-8") print(resp) print(type(resp)) 

执行结果:

{"msg":"登录成功","code":0,"data":{"id":"22299","username":"xxxxx","nickname":"","mobile":"","email":"","avatar":"http://shop-xo.hctestedu.com/static/index/default/images/default-user-avatar.jpg","alipay_openid":"","weixin_openid":"","weixin_unionid":"","weixin_web_openid":"","baidu_openid":"","toutiao_openid":"","qq_openid":"","qq_unionid":"","integral":"0","locking_integral":"0","referrer":"0","add_time":"1678005098","add_time_text":"2023-03-05 16:31:38","mobile_security":"","email_security":"","user_name_view":"xxxxx","is_mandatory_bind_mobile":0,"token":"d653d78ac417f65e1cd38c6f3e220341"}} <class 'str'> 

七、获取响应结果:最原生的状态,对象在内存中的地址:res.raw

print(response.raw) print(type(response.raw)) 

执行结果:

<urllib3.response.HTTPResponse object at 0x0000023317D8D880> <class 'urllib3.response.HTTPResponse'> 

八、解析响应数据

响应数据如下:

{ "msg": "登录成功", "code": 0, "data": { "id": "22299", "username": "Summer", "nickname": "", "mobile": "", "email": "", "avatar": "http://shop-xo.hctestedu.com/static/index/default/images/default-user-avatar.jpg", "alipay_openid": "", "weixin_openid": "", "weixin_unionid": "", "weixin_web_openid": "", "baidu_openid": "", "toutiao_openid": "", "qq_openid": "", "qq_unionid": "", "integral": "0", "locking_integral": "0", "referrer": "0", "add_time": "1678005098", "add_time_text": "2023-03-05 16:31:38", "mobile_security": "", "email_security": "", "user_name_view": "chengcheng", "is_mandatory_bind_mobile": 0, "token": "d653d78ac417f65e1cd38c6f3e220341" } } 

通常我们获取响应数据后,是需要进行结果验证的。例如,我想从登录接口的响应中拿到token,供后面的接口请求鉴权使用。

1、字典方式解析及其缺点

上面已经讲到,可以使用response.json()方法拿到一个字典。既然是字典,就可以用处理字典的方式来获取某个字段的值。

resp = response.json() token = resp["data"]["token"] print(token ) 

执行结果:

d653d78ac417f65e1cd38c6f3e220341 

字典解析的缺点:如果接口数据异常,响应体缺少某个字段,就会发生keyerror,导致程序异常。

resp = response.json() token = resp["data"]["token1"] print(token ) 

执行结果:

Traceback (most recent call last):   File "E:Codingpython-workspaceInterface_testfirst_requests.py", line 128, in <module>     token = resp["data"]["token1"] KeyError: 'token1' 

2、Jsonpath表达式解析及其优点

上面的响应body结构比较简单,如果我们要解析特别复杂的响应体,通过字典方式就很复杂。这个时候更推荐jsonpath。需要引入jsonpath库。

import jsonpath  resp = response.json() # 将返回值转换成字典格式 token = jsonpath.jsonpath(resp, '$..token') # token的jsonpath表达式:$..token print(token) 

执行结果:

['d653d78ac417f65e1cd38c6f3e220341'] 

通过结果来看,获取到的token是只有一个元素的列表。我们要想拿到token通过下标访问。
修改上述代码:

import jsonpath  resp = response.json() # 将返回值转换成字典格式 token = jsonpath.jsonpath(resp, '$..token') # token的jsonpath表达式:$..token print(token[0]) 

执行结果:

d653d78ac417f65e1cd38c6f3e220341 

Jsonpath表达式解析的优点如果响应体缺少某个字段,通过Jsonpath表达式解析不到结果,就会返回False,永远不会发生异常。我们可根据返回结果进行后续处理。

import jsonpath  resp = response.json() # 将返回值转换成字典格式 # 使用错误的jsonpath表达式 token = jsonpath.jsonpath(resp, '$..token1') # token的jsonpath表达式:$..token1 if isinstance(token, List): print(f'可以解析到token,值为:{token[0]}') else: print(f'解析不到token,结果为:{token}') # 使用正确的jsonpath表达式 token = jsonpath.jsonpath(resp, '$..token') # token的jsonpath表达式:$..token if isinstance(token, List): print(f'可以解析到token,值为:{token[0]}') else: print(f'解析不到token,结果为:{token}') 

执行结果:

解析不到token,结果为:False 可以解析到token,值为:d653d78ac417f65e1cd38c6f3e220341 

3、如何知道自己写的jsonpath表达式是否正确呢?

jsonpath在线校验工具:http://jsonpath.com/
将response粘贴在Inputs区域,在JSONPath区域输入表达式,在Evaluation Results区域查看是否解析到期望的值。当解析不到值时,返回的是空列表(No match)
Python发送Post请求及解析响应结果jsonpath表达式语法
Python发送Post请求及解析响应结果

九、获取请求的信息

print(f'请求url:{response.request.url}') print(f'请求方法:{response.request.method}') print(f'请求Header:{response.request.headers}') print(f'请求路径:{response.request.path_url}') 

执行结果:

请求url:http://shop-xo.hctestedu.com/index.php?s=api/user/login&application=app&application_client_type=weixin 请求方法:POST 请求Header:{'User-Agent': 'python-requests/2.28.1', 'Accept-Encoding': 'gzip, deflate', 'Accept': '*/*', 'Connection': 'keep-alive', 'Content-Length': '69', 'Content-Type': 'application/json'} 请求路径:/index.php?s=api/user/login&application=app&application_client_type=weixin 

十、json=data 和 data=data 参数区别

接口电商项目后台代码(PHP)中,json=data以及data=data这2种参数类型都可以接收。在实际项目应用中,常见的报文格式是application/json。因此最常使用的是json=data

1、json=data

请求头默认为:Content-Type=application/json

url = 'http://shop-xo.hctestedu.com/index.php?s=api/user/login' res = requests.post(url=url, json=data, params=param_data) # 查看请求中的请求头信息,Content-Type=application/json print(res.request.headers) print(res.text) 

执行结果:

{'User-Agent': 'python-requests/2.28.1', 'Accept-Encoding': 'gzip, deflate', 'Accept': '*/*', 'Connection': 'keep-alive', 'Content-Length': '69', 'Content-Type': 'application/json'} {"msg":"登录成功","code":0,"data":{"id":"22299","username":"xxxxx","nickname":"","mobile":"","email":"","avatar":"http://shop-xo.hctestedu.com/static/index/default/images/default-user-avatar.jpg","alipay_openid":"","weixin_openid":"","weixin_unionid":"","weixin_web_openid":"","baidu_openid":"","toutiao_openid":"","qq_openid":"","qq_unionid":"","integral":"0","locking_integral":"0","referrer":"0","add_time":"1678005098","add_time_text":"2023-03-05 16:31:38","mobile_security":"","email_security":"","user_name_view":"xxxxx","is_mandatory_bind_mobile":0,"token":"d653d78ac417f65e1cd38c6f3e220341"}}  

2、data=data

请求头默认为:application/x-www-form-urlencoded

url = 'http://shop-xo.hctestedu.com/index.php?s=api/user/login' res = requests.post(url=url, data=data, params=param_data) # 查看请求中的请求头信息,Content-Type=application/x-www-form-urlencoded print(res.request.headers) print(res.text) 

执行结果:

{'User-Agent': 'python-requests/2.28.1', 'Accept-Encoding': 'gzip, deflate', 'Accept': '*/*', 'Connection': 'keep-alive', 'Content-Length': '50', 'Content-Type': 'application/x-www-form-urlencoded'} {"msg":"登录成功","code":0,"data":{"id":"22299","username":"xxxxx","nickname":"","mobile":"","email":"","avatar":"http://shop-xo.hctestedu.com/static/index/default/images/default-user-avatar.jpg","alipay_openid":"","weixin_openid":"","weixin_unionid":"","weixin_web_openid":"","baidu_openid":"","toutiao_openid":"","qq_openid":"","qq_unionid":"","integral":"0","locking_integral":"0","referrer":"0","add_time":"1678005098","add_time_text":"2023-03-05 16:31:38","mobile_security":"","email_security":"","user_name_view":"xxxxx","is_mandatory_bind_mobile":0,"token":"d653d78ac417f65e1cd38c6f3e220341"}} 

3、设置请求头

如果是java项目,spring会将请求实体的内容自动转换为Bean,但前提是请求的Content-Type必须设置为application/json

在请求头中定义发送报文的格式

1、Content-Type: application/json

headers = { 'Content-Type': 'application/json' # 'Content-Type': 'application/x-www-form-urlencoded' } url = 'http://shop-xo.hctestedu.com/index.php?s=api/user/login' res = requests.post(url=url, params=param_data, json=data, headers=headers) print(res.request.headers) 

执行结果:

{'User-Agent': 'python-requests/2.28.1', 'Accept-Encoding': 'gzip, deflate', 'Accept': '*/*', 'Connection': 'keep-alive', 'Content-Type': 'application/json', 'Content-Length': '50'} 

2、Content-Type:application/x-www-form-urlencoded

headers = { # 'Content-Type': 'application/json' 'Content-Type': 'application/x-www-form-urlencoded' } url = 'http://shop-xo.hctestedu.com/index.php?s=api/user/login' res = requests.post(url=url, params=param_data, data=data, headers=headers) print(res.request.headers) 

执行结果:

{'User-Agent': 'python-requests/2.28.1', 'Accept-Encoding': 'gzip, deflate', 'Accept': '*/*', 'Connection': 'keep-alive', 'Content-Type': 'application/x-www-form-urlencoded', 'Content-Length': '69'}  

十一、Json和字典数据转换

1、json.dumps(),将字典转换成Json

使用json.dumps()可以将字典转换成Json

test = { "msg": "登录成功", "code": 0, "data": { "id": "22299", "username": "Summer", "nickname": "", "mobile": "", "email": "", "avatar": "http://shop-xo.hctestedu.com/static/index/default/images/default-user-avatar.jpg", "alipay_openid": "", "weixin_openid": "", "weixin_unionid": "", "weixin_web_openid": "", "baidu_openid": "", "toutiao_openid": "", "qq_openid": "", "qq_unionid": "", "integral": "0", "locking_integral": "0", "referrer": "0", "add_time": "1678005098", "add_time_text": "2023-03-05 16:31:38", "mobile_security": "", "email_security": "", "user_name_view": "chengcheng", "is_mandatory_bind_mobile": 0, "token": "d653d78ac417f65e1cd38c6f3e220341" } } print(type(test)) print(json.dumps(test)) print(type(json.dumps(test))) 

执行结果:

<class 'dict'> {"msg": "u767bu5f55u6210u529f", "code": 0, "data": {"id": "22299", "username": "Summer", "nickname": "", "mobile": "", "email": "", "avatar": "http:\/\/shop-xo.hctestedu.com\/static\/index\/default\/images\/default-user-avatar.jpg", "alipay_openid": "", "weixin_openid": "", "weixin_unionid": "", "weixin_web_openid": "", "baidu_openid": "", "toutiao_openid": "", "qq_openid": "", "qq_unionid": "", "integral": "0", "locking_integral": "0", "referrer": "0", "add_time": "1678005098", "add_time_text": "2023-03-05 16:31:38", "mobile_security": "", "email_security": "", "user_name_view": "chengcheng", "is_mandatory_bind_mobile": 0, "token": "d653d78ac417f65e1cd38c6f3e220341"}} <class 'str'> 

2、json.loads(),将Json转换成字典

使用json.loads()可以将Json转换成字典

print(json.loads(json.dumps(test))) print(type(json.loads(json.dumps(test)))) 

执行结果:

{'msg': '登录成功', 'code': 0, 'data': {'id': '22299', 'username': 'Summer', 'nickname': '', 'mobile': '', 'email': '', 'avatar': 'http:\/\/shop-xo.hctestedu.com\/static\/index\/default\/images\/default-user-avatar.jpg', 'alipay_openid': '', 'weixin_openid': '', 'weixin_unionid': '', 'weixin_web_openid': '', 'baidu_openid': '', 'toutiao_openid': '', 'qq_openid': '', 'qq_unionid': '', 'integral': '0', 'locking_integral': '0', 'referrer': '0', 'add_time': '1678005098', 'add_time_text': '2023-03-05 16:31:38', 'mobile_security': '', 'email_security': '', 'user_name_view': 'chengcheng', 'is_mandatory_bind_mobile': 0, 'token': 'd653d78ac417f65e1cd38c6f3e220341'}} <class 'dict'>  

3、json格式报文发送

方法一:参数是data,值:将字典data转换成json

url = 'http://shop-xo.hctestedu.com/index.php?s=api/user/login' headers = { 'Content-Type': 'application/json' } res = requests.post(url=url, data=json.dumps(data), headers=headers) print(res.text) 

方法二:参数是json,值:字典data

url = 'http://shop-xo.hctestedu.com/index.php?s=api/user/login' res = requests.post(url=url, json=data) print(res.text) print(res.json()) print(type(res.json())) assert "登录成功" == res.json()['msg'] 

十二、获取接口响应时间

url = 'http://shop-xo.hctestedu.com/index.php?s=api/user/login' res = requests.post(url=url, json=data) print(res.text) # 获取接口响应时间,单位秒 print(r.elapsed.total_seconds()) 

执行结果:

{"msg":"登录成功","code":0,"data":{"body_html":""}} 0.078264  

十三、接口调用失败处理

同一个用例中有多个接口调用,一个接口调用失败如何防止程序终止?
用于判断接口请求的状态码是否为200,如果是,则返回none,如果不是则返回异常。
调用接口时结合try…except进行使用。

# 模拟接口404,使用不存在的request url: login1 url = 'http://shop-xo.hctestedu.com/index.php?s=api/user/login1' res = requests.post(url=url, json=data) try: assert 200 == res.status_code except: # 异常处理1:直接跳过,可继续执行后面代码 # pass # 异常处理2:打印详细异常信息 print(res.status_code)     res.raise_for_status() else: print(res.text) 

执行结果:

404 Traceback (most recent call last):   File "E:Codingpython-workspaceInterface_testfirst_requests.py", line 220, in <module>     assert 200 == res.status_code AssertionError  During handling of the above exception, another exception occurred:  Traceback (most recent call last):   File "E:Codingpython-workspaceInterface_testfirst_requests.py", line 226, in <module>     res.raise_for_status()   File "D:DeveloperPythonPython310libsite-packagesrequestsmodels.py", line 1021, in raise_for_status     raise HTTPError(http_error_msg, response=self) requests.exceptions.HTTPError: 404 Client Error: Not Found for url: http://shop-xo.hctestedu.com/index.php?s=api/user/login1 

十四、接口超时

url = 'http://shop-xo.hctestedu.com/index.php?s=api/user/login' try:     res = requests.post(url=url, json=data, timeout=0.01) # timeout,单位秒 except (TimeoutError, ReadTimeout, ConnectTimeout): # ConnectTimeout:指的是建立连接所用的时间,适用于网络状况正常的情况下,两端连接所用的时间。 # ReadTimeout:指的是建立连接后从服务器读取到可用资源所用的时间。 print("发生错误,请稍后重试") else: # 获取接口响应时间,单位秒 print(res.elapsed.total_seconds()) print(res.text) 

执行结果:

发生错误,请稍后重试 

当把timeout改成0.1,执行结果:

0.07419 {"msg":"登录成功","code":0,"data":{"body_html":""}} 

www.npspro.top互联侠客
IT互联侠客 » Python发送Post请求及解析响应结果

发表回复

最TOP的Docker,软路由,虚拟机等学习资料

立即查看 了解详情