Python网络爬虫使用代理轮换IP时是否需主动结束请求避免过载目标服务器
问题结论
你需要主动构建请求终止相关的功能,这不仅能降低目标服务器负载,也能提升你自身爬虫的运行效率。
具体原因
- 你当前的代码没有设置请求超时,一旦出现网络波动或者目标服务器响应缓慢,请求会一直挂起,长期占用目标服务器的连接资源,也会浪费你本地的线程池资源,无形中拉高目标服务器的负载。
- 现有重试逻辑存在缺陷:仅判断了200和404状态码,遇到429限流、500/502/503服务端异常时会直接重试,没有间隔也没有终止逻辑,大量无意义的重复请求会直接加重目标服务的压力。
- 当前代码还有个潜在bug:触发
ConnectionError时你把response赋值为空字符串,后续判断response.status_code会直接抛出属性错误,导致线程异常退出。
优化参考代码
import requests import time from bs4 import BeautifulSoup from urllib.parse import urlencode import concurrent.futures list_of_urls = ['https://www.example'] NUM_RETRIES = 3 NUM_THREADS = 5 # 统一设置请求超时时间,单位秒 REQUEST_TIMEOUT = 10 # 重试间隔时间,单位秒 RETRY_DELAY = 2 def scrape_url(url): params = {'api_key': 'API_KEY', 'url': url} response = None for _ in range(NUM_RETRIES): try: # 加timeout参数主动结束超时请求 response = requests.get('http://api.scraperapi.com/', params=urlencode(params), timeout=REQUEST_TIMEOUT) # 遇到正常响应或者404直接终止重试 if response.status_code in [200, 404]: break # 遇到限流、服务端错误,先等一会再重试,减少服务器压力 if response.status_code in [429, 500, 502, 503]: time.sleep(RETRY_DELAY) continue # 遇到其他客户端错误,直接终止重试,没有必要再请求 if 400 <= response.status_code < 500: break except requests.exceptions.RequestException: # 捕获所有请求相关异常,避免线程崩溃,等待后重试 time.sleep(RETRY_DELAY) continue # 先判断response是否存在,再判断状态码,避免属性错误 if response and response.status_code == 200: # 解析逻辑 pass if __name__ == "__main__": with concurrent.futures.ThreadPoolExecutor(max_workers=NUM_THREADS) as executor: executor.map(scrape_url, list_of_urls)
额外降低目标服务器负载的建议
- 并发数不要设置过高,爬取小规模站点时可以把线程数降到2-3,避免短时间内建立过多连接
- 可以在每次请求完成后加随机的延迟,避免请求频率过于固定被识别,也能降低服务器压力
- 提前梳理要爬取的URL,避免重复爬取无效页面
内容的提问来源于stack exchange,提问作者Liam
相关产品推荐
相关产品推荐

