网上介绍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不怎么感冒,速度比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 Key‘ 14 } 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的源代码去查找对比,看看是到底哪里传参不一样。。结果是果然有差异:
requests发送post请求时,参数data可以是字典,列表,元组,bytes,文件等等。。。。
httpx发送post请求时,参数data只能是字典。。。。ctrl+鼠标点击 RequestData 转到_types.py 找到RequestData = dict
但是,但是,,我的代码中 data就是字典格式啊。。。。。。
那问题出在哪里呢,突然想起来,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()
点击绿色小箭头 开始运行,结果成功!
总结,python的第三方库实在太多了,对经常使用的模块应该熟读它的开源代码,细节不能放过。。。。
关于httpx模块和requests模块发送post请求的差异
原文:https://www.cnblogs.com/filexhu/p/15178337.html