Python多線程并發(fā)時(shí)出現(xiàn)503錯(cuò)誤的最佳處理
一、503 錯(cuò)誤產(chǎn)生的原因
在 HTTP 協(xié)議中,503 錯(cuò)誤表示服務(wù)器當(dāng)前無(wú)法處理請(qǐng)求,通常是因?yàn)榉?wù)器暫時(shí)過(guò)載或維護(hù)。在多線程爬蟲(chóng)場(chǎng)景下,503 錯(cuò)誤可能由以下幾種原因引起:
- 服務(wù)器負(fù)載過(guò)高:當(dāng)多個(gè)線程同時(shí)向服務(wù)器發(fā)送請(qǐng)求時(shí),服務(wù)器可能因負(fù)載過(guò)高而拒絕部分請(qǐng)求,返回 503 錯(cuò)誤。
- 請(qǐng)求頻率過(guò)快:如果爬蟲(chóng)的請(qǐng)求頻率超過(guò)了服務(wù)器的處理能力,服務(wù)器可能會(huì)認(rèn)為這是一種攻擊行為,從而返回 503 錯(cuò)誤。
- 服務(wù)器配置問(wèn)題:某些服務(wù)器可能配置了特定的防護(hù)機(jī)制,如防火墻或反爬蟲(chóng)策略,當(dāng)檢測(cè)到異常請(qǐng)求時(shí)會(huì)返回 503 錯(cuò)誤。
- 網(wǎng)絡(luò)問(wèn)題:網(wǎng)絡(luò)不穩(wěn)定或代理服務(wù)器故障也可能導(dǎo)致 503 錯(cuò)誤。
二、503 錯(cuò)誤處理的最佳實(shí)踐
(一)合理控制并發(fā)線程數(shù)量
過(guò)多的并發(fā)線程會(huì)增加服務(wù)器的負(fù)載,導(dǎo)致 503 錯(cuò)誤。因此,合理控制并發(fā)線程的數(shù)量是避免 503 錯(cuò)誤的關(guān)鍵??梢酝ㄟ^(guò)設(shè)置線程池來(lái)限制并發(fā)線程的數(shù)量。
import concurrent.futures
import requests
def fetch_url(url):
try:
response = requests.get(url)
response.raise_for_status()
return response.text
except requests.exceptions.HTTPError as e:
if e.response.status_code == 503:
print(f"503 error occurred for {url}")
# Handle 503 error
else:
raise
def main():
urls = ["http://example.com/page1", "http://example.com/page2", ...]
max_workers = 10 # 控制并發(fā)線程數(shù)量
with concurrent.futures.ThreadPoolExecutor(max_workers=max_workers) as executor:
futures = [executor.submit(fetch_url, url) for url in urls]
for future in concurrent.futures.as_completed(futures):
try:
data = future.result()
# Process data
except Exception as e:
print(f"Error: {e}")
if __name__ == "__main__":
main()
(二)設(shè)置合理的請(qǐng)求間隔
為了避免因請(qǐng)求頻率過(guò)快導(dǎo)致的 503 錯(cuò)誤,可以在請(qǐng)求之間設(shè)置合理的間隔時(shí)間。這可以通過(guò)在請(qǐng)求代碼中添加 <font style="color:rgba(0, 0, 0, 0.9);background-color:rgba(0, 0, 0, 0.03);">time.sleep()</font> 來(lái)實(shí)現(xiàn)。
import time
import requests
def fetch_url(url):
try:
response = requests.get(url)
response.raise_for_status()
return response.text
except requests.exceptions.HTTPError as e:
if e.response.status_code == 503:
print(f"503 error occurred for {url}")
# Handle 503 error
else:
raise
def main():
urls = ["http://example.com/page1", "http://example.com/page2", ...]
for url in urls:
fetch_url(url)
time.sleep(1) # 設(shè)置請(qǐng)求間隔為 1 秒
if __name__ == "__main__":
main()
(三)使用代理服務(wù)器和用戶代理
使用代理服務(wù)器可以隱藏爬蟲(chóng)的真實(shí) IP 地址,減少被服務(wù)器封禁的風(fēng)險(xiǎn)。同時(shí),代理服務(wù)器可以分散請(qǐng)求,降低單個(gè) IP 的請(qǐng)求頻率。服務(wù)器可能會(huì)根據(jù)請(qǐng)求的用戶代理(User-Agent)來(lái)判斷請(qǐng)求是否來(lái)自爬蟲(chóng)。通過(guò)設(shè)置隨機(jī)的用戶代理,可以降低被服務(wù)器識(shí)別為爬蟲(chóng)的風(fēng)險(xiǎn)。
import requests
import time
from requests.adapters import HTTPAdapter
from urllib3.util.retry import Retry
# 代理配置
proxyHost = "www.16yun.cn"
proxyPort = "5445"
proxyUser = "16QMSOML"
proxyPass = "280651"
# 用戶代理池
user_agents = [
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.3",
"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.103 Safari/537.36",
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.0.3 Safari/605.1.15",
"Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:88.0) Gecko/20100101 Firefox/88.0"
]
def get_proxy():
"""獲取認(rèn)證代理"""
return f"http://{proxyUser}:{proxyPass}@{proxyHost}:{proxyPort}"
def create_session():
"""創(chuàng)建帶有重試機(jī)制的會(huì)話"""
session = requests.Session()
retry_strategy = Retry(
total=3,
backoff_factor=1,
status_forcelist=[500, 502, 503, 504]
)
adapter = HTTPAdapter(max_retries=retry_strategy)
session.mount("http://", adapter)
session.mount("https://", adapter)
return session
def fetch_url(url):
"""獲取URL內(nèi)容"""
session = create_session()
proxy = get_proxy()
headers = {"User-Agent": random.choice(user_agents)}
try:
response = session.get(
url,
proxies={"http": proxy, "https": proxy},
headers=headers,
timeout=10
)
response.raise_for_status()
print(f"成功獲取: {url} [狀態(tài)碼: {response.status_code}]")
return response.text
except requests.exceptions.HTTPError as e:
if e.response.status_code == 503:
print(f"503錯(cuò)誤: {url} - 服務(wù)器暫時(shí)不可用")
# 可以在這里添加重試邏輯或記錄到日志
else:
print(f"HTTP錯(cuò)誤 {e.response.status_code}: {url}")
raise
except Exception as e:
print(f"請(qǐng)求異常: {url} - {str(e)}")
raise
def main():
"""主函數(shù)"""
urls = [
"http://example.com/page1",
"http://example.com/page2",
"http://example.com/page3"
]
for url in urls:
try:
fetch_url(url)
time.sleep(1) # 請(qǐng)求間隔
except Exception as e:
print(f"處理 {url} 時(shí)出錯(cuò): {e}")
continue
if __name__ == "__main__":
import random # 為user_agents隨機(jī)選擇
main()
(四)重試機(jī)制
當(dāng)遇到 503 錯(cuò)誤時(shí),可以設(shè)置重試機(jī)制,等待一段時(shí)間后再次嘗試請(qǐng)求。這可以通過(guò) <font style="color:rgba(0, 0, 0, 0.9);background-color:rgba(0, 0, 0, 0.03);">requests</font> 庫(kù)的 <font style="color:rgba(0, 0, 0, 0.9);background-color:rgba(0, 0, 0, 0.03);">Session</font> 對(duì)象和 <font style="color:rgba(0, 0, 0, 0.9);background-color:rgba(0, 0, 0, 0.03);">Retry</font> 類來(lái)實(shí)現(xiàn)。
import requests
from requests.adapters import HTTPAdapter
from requests.packages.urllib3.util.retry import Retry
def fetch_url(url):
session = requests.Session()
retries = Retry(total=5, backoff_factor=1, status_forcelist=[503])
session.mount("http://", HTTPAdapter(max_retries=retries))
try:
response = session.get(url)
response.raise_for_status()
return response.text
except requests.exceptions.HTTPError as e:
if e.response.status_code == 503:
print(f"503 error occurred for {url}")
# Handle 503 error
else:
raise
def main():
urls = ["http://example.com/page1", "http://example.com/page2", ...]
for url in urls:
fetch_url(url)
if __name__ == "__main__":
main()
三、綜合實(shí)踐案例
以下是一個(gè)綜合運(yùn)用上述最佳實(shí)踐的完整代碼示例:
import concurrent.futures
import requests
import time
import random
from requests.adapters import HTTPAdapter
from requests.packages.urllib3.util.retry import Retry
user_agents = [
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.3",
"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.103 Safari/537.36",
# 添加更多用戶代理
]
proxies = ["http://proxy1.example.com:8080", "http://proxy2.example.com:8080", ...]
def fetch_url(url):
headers = {"User-Agent": random.choice(user_agents)}
session = requests.Session()
retries = Retry(total=5, backoff_factor=1, status_forcelist=[503])
session.mount("http://", HTTPAdapter(max_retries=retries))
try:
response = session.get(url, headers=headers, proxies=random.choice(proxies))
response.raise_for_status()
return response.text
except requests.exceptions.HTTPError as e:
if e.response.status_code == 503:
print(f"503 error occurred for {url}")
# Handle 503 error
else:
raise
def main():
urls = ["http://example.com/page1", "http://example.com/page2", ...]
max_workers = 10 # 控制并發(fā)線程數(shù)量
with concurrent.futures.ThreadPoolExecutor(max_workers=max_workers) as executor:
futures = [executor.submit(fetch_url, url) for url in urls]
for future in concurrent.futures.as_completed(futures):
try:
data = future.result()
# Process data
except Exception as e:
print(f"Error: {e}")
time.sleep(1) # 設(shè)置請(qǐng)求間隔為 1 秒
if __name__ == "__main__":
main()
四、總結(jié)
在 Python 爬蟲(chóng)多線程并發(fā)時(shí),503 錯(cuò)誤是一個(gè)常見(jiàn)的問(wèn)題。通過(guò)合理控制并發(fā)線程數(shù)量、設(shè)置合理的請(qǐng)求間隔、使用代理服務(wù)器、添加重試機(jī)制和偽裝用戶代理等方法,可以有效降低 503 錯(cuò)誤的發(fā)生概率,提高爬蟲(chóng)的穩(wěn)定性和可靠性。在實(shí)際開(kāi)發(fā)中,開(kāi)發(fā)者需要根據(jù)目標(biāo)網(wǎng)站的具體情況,靈活運(yùn)用這些最佳實(shí)踐方法,以確保爬蟲(chóng)的高效運(yùn)行。
到此這篇關(guān)于Python多線程并發(fā)時(shí)出現(xiàn)503錯(cuò)誤的最佳處理的文章就介紹到這了,更多相關(guān)Python處理503錯(cuò)誤內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
基于OpenCV目標(biāo)跟蹤實(shí)現(xiàn)人員計(jì)數(shù)器
這篇文章主要介紹了如何利用Python OpenCV這兩者來(lái)創(chuàng)建更準(zhǔn)確的人員計(jì)數(shù)器,文中的示例代碼講解詳細(xì),感興趣的小伙伴快來(lái)跟隨小編學(xué)習(xí)一下吧2022-03-03
python使用Streamlit庫(kù)制作Web可視化頁(yè)面
一談到Web頁(yè)面,可能大家首先想到就是HTML,CSS或JavaScript。 本次小F就給大家介紹一下如何用Python制作一個(gè)數(shù)據(jù)可視化網(wǎng)頁(yè),使用到的是Streamlit庫(kù)。輕松的將一個(gè)Excel數(shù)據(jù)文件轉(zhuǎn)換為一個(gè)Web頁(yè)面,提供給所有人在線查看。2021-05-05
python采用getopt解析命令行輸入?yún)?shù)實(shí)例
這篇文章主要介紹了python采用getopt解析命令行輸入?yún)?shù)實(shí)例,非常具有實(shí)用價(jià)值,需要的朋友可以參考下2014-09-09
使用Pycharm創(chuàng)建一個(gè)Django項(xiàng)目的超詳細(xì)圖文教程
Django是比較經(jīng)典的Python web框架,最近剛好在項(xiàng)目中用到了Django,所以下面這篇文章主要給大家介紹了關(guān)于使用Pycharm創(chuàng)建一個(gè)Django項(xiàng)目的超詳細(xì)圖文教程,文中介紹的非常詳細(xì),需要的朋友可以參考下2022-08-08
python中使用input()函數(shù)獲取用戶輸入值方式
這篇文章主要介紹了python中使用input()函數(shù)獲取用戶輸入值方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-05-05
django中使用Celery 布式任務(wù)隊(duì)列過(guò)程詳解
這篇文章主要介紹了django中使用Celery 布式任務(wù)隊(duì)列實(shí)現(xiàn)過(guò)程詳解,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-07-07
python實(shí)現(xiàn)nao機(jī)器人身體軀干和腿部動(dòng)作操作
這篇文章主要為大家詳細(xì)介紹了python實(shí)現(xiàn)nao機(jī)器人身體軀干和腿部動(dòng)作操作,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-04-04
python實(shí)現(xiàn)查找excel里某一列重復(fù)數(shù)據(jù)并且剔除后打印的方法
這篇文章主要介紹了python實(shí)現(xiàn)查找excel里某一列重復(fù)數(shù)據(jù)并且剔除后打印的方法,涉及Python使用xlrd模塊操作Excel的相關(guān)技巧,需要的朋友可以參考下2015-05-05

