News from this site

 Rental advertising space, please contact the webmaster if you need cooperation


+focus
focused

classification  

no classification

tag  

no tag

date  

no datas

Python发送Post请求及解析响应结果

posted on 2023-05-21 16:38     read(643)     comment(0)     like(30)     collect(2)


1. Post request

1. Use python to send a Post request

Sometimes there are many parameters in the request url.

1.1 Example 1

For accounts and pwd, please go to http://shop-xo.hctestedu.com/ to register.

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)

Results of the:

{"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 Example 2

Use the variable length parameter params to encapsulate the parameters required in the url separately.

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)

Results of the:

{"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"}}

Two, get the Response body

1、response.text

Use type() to view the type of response.text, which is 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))

Results of the:

{"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()

Use type() to view the type of response.json(), which is 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()))

Results of the:

{"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'>

3. Get the response status code : res.status_code

print(response.status_code)

Results of the:

200

More status codes:

状态代码有三位数字组成,第一个数字定义了响应的类别,共分五种类别:
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	//服务器当前不能处理客户端的请求,一段时间后可能恢复正常

4. Get response cookies: res.cookies

print(response.cookies)

Results of the:

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

5. Get response headers: res.headers

print(response.headers)

Results of the:

{'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'}

6. Get the original content of the response result: res.content

content, which has not been compiled, is displayed in bytes. The text mentioned above is compiled. Automatically find the encoding format in the request header and parse it.

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

Results of the:

b'{"msg":"\xe7\x99\xbb\xe5\xbd\x95\xe6\x88\x90\xe5\x8a\x9f","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 also supports manual encoding, such as using utf-8 encoding , the encoded is str type, json is essentially a string type

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

Results of the:

{"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'>

7. Obtain the response result: the most original state, the address of the object in memory: res.raw

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

Results of the:

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

8. Parsing the response data

The response data is as follows:

{
    "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:\Coding\python-workspace\Interface_test\first_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)
insert image description herejsonpath表达式语法
insert image description here

九、获取请求的信息

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": "\u767b\u5f55\u6210\u529f", "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:\Coding\python-workspace\Interface_test\first_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:\Coding\python-workspace\Interface_test\first_requests.py", line 226, in <module>
    res.raise_for_status()
  File "D:\Developer\Python\Python310\lib\site-packages\requests\models.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":""}}


Category of website: technical article > Blog

Author:Soledad

link:http://www.pythonblackhole.com/blog/article/25286/8f335e533da587787234/

source:python black hole net

Please indicate the source for any form of reprinting. If any infringement is discovered, it will be held legally responsible.

30 0
collect article
collected

Comment content: (supports up to 255 characters)