关于httpx模块和requests模块发送post请求的差异

网上介绍httpx和requests两个模块的资料不少,他们的优劣这里不谈。

说下在实际使用中两者参数的细微差别。

今天 研究人像转动漫图像的实现,没用opencv实现,就找了百度的api来实现,官网有现成例子参考。

自己写的实现代码:

import json
import base64
import requests


# 获取Access Token
url = https://aip.baidubce.com/oauth/2.0/token
post_data = {
    grant_type: client_credentials,
    client_id: App Key,
    client_secret: Secret Key
}

access_token = None
response = httpx.post(url=url, data=post_data)
if response.status_code == 200:
    json_data = response.json()
    access_token = json_data[access_token]
    print(access_token)
    term_of_validity = json_data[expires_in]
    print(f有效使用期为{term_of_validity}秒.[有效期30天])

"""
打开图片
base64编码后大小不超过10M(参考:原图大约为8M以内),最短边至少10px,最长边最大5000px,
长宽比4:1以内。注意:图片的base64编码是不包含图片头的,如(data:image/jpg;base64,)
"""
img_path = images/1.png#input(u‘请输入图片全路径:\n‘)
# with open(img_path, ‘rb‘) as fp:
fp = open(img_path, rb)
img = base64.b64encode(fp.read())
# 人脸动漫化
api_url = https://aip.baidubce.com/rest/2.0/image-process/v1/selfie_anime

print(type(img))
params = {
    image: img,
    access_token: access_token,
}
headers_ = {
    # post参数是以表单方式提交,不是json
    Content-Type: application/x-www-form-urlencoded
}
response_ = requests.post(api_url, data=params, headers=headers_)
if response_:
    print(response_.json())
    # 保存文件
    fp = open(images/动漫图.jpg, wb)
    img = (response_.json()[image])
    fp.write(base64.b64decode(img))
fp.close()

执行成功,生成了个不怎么好看的动漫图。。。‘image‘的值就是生成的动漫图片的base64编码格式,需要解码在保存即可。

 

关于httpx模块和requests模块发送post请求的差异

然而,问题来了,因为以往写爬虫时喜欢用httpx模块,对requests不怎么感冒,速度比httpx差太多了,所以我把上述代码中发送请求的resquests模块替换成了httpx

代码如下:

 1 import json
 2 import base64
 3 import httpx
 4 import requests
 5 
 6 
 7 # 获取Access Token
 8 url = https://aip.baidubce.com/oauth/2.0/token
 9 post_data = {
10     grant_type: client_credentials,
11     # 这两个参数的值 需要注册百度ai应用可以获取
12     client_id: App Key,
13     client_secret: Secret Key14 }
15 
16 access_token = None
17 response = httpx.post(url=url, data=post_data)
18 if response.status_code == 200:
19     json_data = response.json()
20     access_token = json_data[access_token]
21     # print(access_token)
22     print(access_token is: 保密,自己可以去注册百度获取)
23     term_of_validity = json_data[expires_in]
24     print(f有效使用期为{term_of_validity}秒.[有效期30天])
25 
26 """
27 打开图片
28 base64编码后大小不超过10M(参考:原图大约为8M以内),最短边至少10px,最长边最大5000px,
29 长宽比4:1以内。注意:图片的base64编码是不包含图片头的,如(data:image/jpg;base64,)
30 """
31 img_path = images/1.png#input(u‘请输入图片全路径:\n‘)
32 # with open(img_path, ‘rb‘) as fp:
33 fp = open(img_path, rb)
34 img = base64.b64encode(fp.read())
35 # 人脸动漫化
36 api_url = https://aip.baidubce.com/rest/2.0/image-process/v1/selfie_anime
37 
38 print(type(img))
39 params = {
40     image: img,
41     access_token: access_token,
42 }
43 headers_ = {
44     Content-Type: application/x-www-form-urlencoded
45 }
46 response_ = httpx.post(api_url, data=params, headers=headers_)
47 # response_ = requests.post(api_url, data=params, headers=headers_)
48 if response_:
49     print(response_.json())
50     # 保存文件
51     fp = open(images/动漫图.jpg, wb)
52     img = (response_.json()[image])
53    fp.write(base64.b64decode(img))
54 fp.close()

只是把requests替换成了httpx,结果 却出错了,提示 图片格式错误,什么鬼。。。。

关于httpx模块和requests模块发送post请求的差异

不得以 又回头去翻httpx和requests的源代码去查找对比,看看是到底哪里传参不一样。。结果是果然有差异:

requests发送post请求时,参数data可以是字典,列表,元组,bytes,文件等等。。。。

关于httpx模块和requests模块发送post请求的差异

httpx发送post请求时,参数data只能是字典。。。。ctrl+鼠标点击 RequestData 转到_types.py 找到RequestData = dict

关于httpx模块和requests模块发送post请求的差异

关于httpx模块和requests模块发送post请求的差异

但是,但是,,我的代码中 data就是字典格式啊。。。。。。

关于httpx模块和requests模块发送post请求的差异


 那问题出在哪里呢,突然想起来,img是bytes类型(经过base64编码了),难道 这里必须转成string?想不如做,于是 代码改成了

import json
import base64
import httpx
import requests


# 获取Access Token
url = https://aip.baidubce.com/oauth/2.0/token
post_data = {
    grant_type: client_credentials,
    client_id: App Key,
    client_secret: Secret Key
}

access_token = None
response = httpx.post(url=url, data=post_data)
if response.status_code == 200:
    json_data = response.json()
    access_token = json_data[access_token]
    # print(access_token)
    print(access_token is: 保密,自己可以去注册百度获取)
    term_of_validity = json_data[expires_in]
    print(f有效使用期为{term_of_validity}秒.[有效期30天])

"""
打开图片
base64编码后大小不超过10M(参考:原图大约为8M以内),最短边至少10px,最长边最大5000px,
长宽比4:1以内。注意:图片的base64编码是不包含图片头的,如(data:image/jpg;base64,)
"""
img_path = images/1.png#input(u‘请输入图片全路径:\n‘)
# with open(img_path, ‘rb‘) as fp:
fp = open(img_path, rb)
img = base64.b64encode(fp.read())
# 人脸动漫化
api_url = https://aip.baidubce.com/rest/2.0/image-process/v1/selfie_anime

print(type(img))
params = {
    # ‘image‘: img,
    ‘image‘: str(img, encoding="utf-8"),
    access_token: access_token,
}
headers_ = {
    Content-Type: application/x-www-form-urlencoded
}
response_ = httpx.post(api_url, data=params, headers=headers_)
# response_ = requests.post(api_url, data=params, headers=headers_)
if response_:
    print(response_.json())
    # 保存文件
    fp = open(images/动漫图.jpg, wb)
    img = (response_.json()[image])
    fp.write(base64.b64decode(img))
fp.close()

点击绿色小箭头 开始运行,结果成功!

关于httpx模块和requests模块发送post请求的差异

总结,python的第三方库实在太多了,对经常使用的模块应该熟读它的开源代码,细节不能放过。。。。

关于httpx模块和requests模块发送post请求的差异

上一篇:微信公众号和微信文章纳入搜狗百科词条


下一篇:Java基础知识08--lambda表达式与函数式接口详解