Python Requests.post()請求失敗時的retry設(shè)置方式
Python Requests.post()請求失敗retry設(shè)置
1. 問題描述
通常,我們在做爬蟲工作或遠(yuǎn)程接口調(diào)用的過程中,往往由于訪問頻率過快等原因遇到連接超時的報錯問題,利用最近調(diào)用api.ai.qq.com某個接口舉例如下:
Traceback (most recent call last):
<class 'Exception'> : HTTPSConnectionPool(host='api.ai.qq.com', port=443):
Max retries exceeded with url: /fcgi-bin/nlp/nlp_textpolar (Caused by ProxyError('Cannot connect to proxy.', OSError('Tunnel connection failed: 504 Gateway Time-out',)))
用代碼格式顯示更為清晰:
Traceback (most recent call last): <class 'Exception'> : HTTPSConnectionPool(host='api.ai.qq.com', port=443): Max retries exceeded with url: /fcgi-bin/nlp/nlp_textpolar (Caused by ProxyError('Cannot connect to proxy.', OSError('Tunnel connection failed: 504 Gateway Time-out',)))
之前寫爬蟲時候為了快速解決問題就寫了一堆的while與try來實現(xiàn)鏈接的重新訪問,這種方式可以在一定程度上解決問題,但回看自己的代碼時候總覺得奇丑無比,今天在做一個遠(yuǎn)程接口調(diào)用時候又遇到這個報錯,想著python的requests模塊中一定有內(nèi)置方法來解決這個問題,于是便嘗試了一下,但同時又引發(fā)了另一個小問題,遂決定記錄一下。
2. 解決方案
其實,我們在http請求中遇到連接超時導(dǎo)致訪問中斷的情況時,往往不需要自己來寫重訪問策略,requests模塊中有對應(yīng)的重訪問設(shè)置,可以通過設(shè)置最大重訪問次數(shù),當(dāng)一次訪問失敗時,會自動進(jìn)行重新訪問,實現(xiàn)方式(簡化)如下:
import requests from requests.adapters import HTTPAdapter from requests.packages.urllib3.util import Retry s = requests.Session() s.mount('https://', HTTPAdapter(max_retries=Retry(total=5))) resp_get = s.get(url=http_url, data={'key':'value'}) resp_post = s.post(url=http_url, data={'key':'value'})
可以看到,我們設(shè)置最大重訪問次數(shù)為5。但此時會發(fā)現(xiàn),如果我們使用的是 get()
方法的話則沒有問題,但如果使用 post()
方法的話仍然會報錯。
通過查資料發(fā)現(xiàn),python的requests模塊使用的urllib3,而urllib3默認(rèn)對 post()
方法不設(shè)置重訪問,因此需要我們手動指定才可以,修改如下:
import requests from requests.adapters import HTTPAdapter from requests.packages.urllib3.util import Retry s = requests.Session() s.mount('https://', HTTPAdapter(max_retries=Retry(total=5, method_whitelist=frozenset(['GET', 'POST'])))) # 設(shè)置 post()方法進(jìn)行重訪問 resp_get = s.get(url=http_url, data={'key':'value'}) resp_post = s.post(url=http_url, data={'key':'value'})
這樣再使用requests.post()
時幾乎不會出現(xiàn)超時中斷的情況了!
python requests.post請求404
問題場景
有時候,在編寫一段http接口請求程序時,發(fā)現(xiàn)代碼中的header頭和請求體中都是原網(wǎng)頁中一樣,但是,在實際請求時,接口卻返回404,代碼如下
header = { # ':authority': 'm.ctrip.com', # ':method': 'POST', # ':path': '/restapi/soa2/20405/getPCSightList', # ':scheme': 'https', 'accept': '*/*', 'accept-encoding': 'gzip, deflate, br', 'accept-language': 'zh-CN,zh;q=0.9', 'authorization': 'xx', 'cache-control': "no-cache", 'content-length': '373', 'content-type': 'application/json;charset:utf-8;', 'cookies': 'xx', 'origin': 'https://www.tripadvisor.cn', 'pragma': 'no-cache', 'referer': 'https://www.tripadvisor.cn/Attractions-g60763-New_York_City_New_York-Vacations.html', 'sec-ch-ua': "'.Not/A)Brand';v='99', 'Google Chrome';v='103', 'Chromium';v='103'", 'sec-ch-ua-mobile': '?0', 'sec-ch-ua-platform': 'macOS', 'sec-fetch-dest': 'empty', 'sec-fetch-mode': 'cors', 'sec-fetch-site': 'cross-site', 'user-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.0.0 Safari/537.36', 'x-ta-uid': 'cd58b674-7dba-484a-a908-3239120cd728' } url = 'https://m.ctrip.com/restapi/soa2/20405/getPCSightList' data = {"geoId":60763,"pageIndex":1,"pageSize":30,"travelRanking":"false","needSelectedFilters":"true","filters":[{"type":"subcategory","param":""},{"type":"subtype","param":""},{"type":"neighborhood","param":""},{"type":"travelerRating","param":""},{"type":"awards","param":""},{"type":"waypointairport","param":""},{"type":"waypointstation","param":""},{"type":"other","param":""}]} response = requests.post(url=url, data=data, headers=header) print(response.status_code)
運(yùn)行結(jié)果為
問題分析
既然404,那就排查問題,data和header都是直接從復(fù)制瀏覽器中復(fù)制過來的,不會有問題,那有問題的必然是request.post中的方法問題
- 查看request.post源碼
從源碼中可以看到,request.post可以接受兩個參數(shù),一個是data,還有一個是json,
data是以字典的形式發(fā)送body,json則是以json數(shù)據(jù)格式發(fā)送body
通過這兩個注釋可以很明顯的發(fā)現(xiàn),requests.post在發(fā)送請求時,會根據(jù)當(dāng)前傳遞的參數(shù)來選擇不同的方式,可以理解為一種是表單形式,還有一種是json格式
- postman測試
通過postman來測試兩種不同請求下的情況
form表單
Json數(shù)據(jù)
通過postman測試可以發(fā)現(xiàn),當(dāng)前服務(wù)后端接口僅接受json格式的數(shù)據(jù),即content-type為application.json
問題解決
將原先代碼中data替換成json
response = requests.post(url=url, json=data, headers=JsonHeader)
這個時候肯定有人會問,那我使用data傳遞數(shù)據(jù)時,將header頭中的content-type指定為application/json不就行了,但其實是不行的,就算自己指定了,最后request.body的值也是類似于key1=value1&key2=value2這種形式
心得
1.當(dāng)request.post使用json來傳遞參數(shù)時,即使不指定content-type類型,也會默認(rèn)指定application/json
2.使用data傳遞參數(shù)時,將會以表單的形式進(jìn)行提交,并且后續(xù)將通過urlencode轉(zhuǎn)換成字符串,及key1=value1&key2=value2的形式
3.使用data時,即使指定了content-type也不會生效,后續(xù)將會被默認(rèn)替換掉
因此,需要根據(jù)自己實際情況來分析當(dāng)前接口接收數(shù)據(jù)時使用的是什么格式,但目前一般的網(wǎng)站都開始采用application/jsond的數(shù)據(jù)格式
總結(jié)
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關(guān)文章
Python?Opencv中獲取卷積核的實現(xiàn)代碼
這篇文章主要介紹了Python?Opencv中獲取卷積核的實現(xiàn)代碼,本文通過實例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2022-07-07Python編程matplotlib繪圖挑鉆石seaborn小提琴和箱線圖
這篇文章主要為大家介紹了Python編程如何使用matplotlib繪圖來挑出完美的鉆石以及seaborn小提琴和箱線圖,有需要的朋友可以借鑒參考下,希望能夠優(yōu)速幫助2021-10-10python數(shù)據(jù)寫入Excel文件中的實現(xiàn)步驟
Python作為時下流行的語言,數(shù)據(jù)寫入Excel是必要的操作,下面這篇文章主要給大家介紹了關(guān)于python數(shù)據(jù)寫入Excel文件中的簡單實現(xiàn)方法,文中通過實例代碼介紹的非常詳細(xì),需要的朋友可以參考下2022-04-04Python進(jìn)階之如何快速將變量插入有序數(shù)組
在我們學(xué)習(xí)python的過程中,學(xué)習(xí)序列是一門必修課。本文我們就來一起看一看Python是如何快速將變量插入有序數(shù)組的,感興趣的可以了解一下2023-04-04使用Python?Matplotlib處理地理數(shù)據(jù)可視化
地理數(shù)據(jù)可視化是數(shù)據(jù)科學(xué)中一個重要的領(lǐng)域,它幫助我們理解和分析與地理位置相關(guān)的數(shù)據(jù),Python?提供了強(qiáng)大的工具來處理地理數(shù)據(jù),本文將介紹如何使用?Python?Matplotlib?處理地理數(shù)據(jù)可視化,包括基礎(chǔ)概念、常用庫、數(shù)據(jù)處理以及實際案例,需要的朋友可以參考下2024-11-11