網上介紹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的第三方庫實在太多了,對經常使用的模塊應該熟讀它的開源代碼,細節不能放過。。。。