如何让线程持续使用同一代理直至返回403响应状态码?
问题:多线程中让单个线程持续使用同一代理直至返回403
现有多线程代码(示例启动50个线程),规则为每个线程仅能使用一个代理且单个代理不可被多线程共用,但当前每次循环都会获取新的随机代理。需求是:同一线程持续使用同一代理,直到请求返回403状态码后再更换新代理。
原代码问题点
原代码通过上下文管理器available_proxies.proxies获取代理,每次with块结束后会自动释放代理,导致每次循环都重新获取新代理,无法满足线程持续使用同一代理的需求。
修改后的解决方案
调整代理管理器的逻辑,让线程主动控制代理的占用与释放,同时修改线程函数,让线程维护自身的代理实例,仅在收到403时更换代理:
import random import threading import time import requests my_proxies = [ 'http://140.99.107.100:2100', 'http://140.99.107.101:2100', 'http://140.99.107.102:2100', 'http://140.99.107.103:2100', 'http://140.99.107.104:2100', 'http://140.99.107.105:2100', 'http://140.99.107.106:2100', 'http://140.99.107.107:2100', 'http://140.99.107.108:2100', 'http://140.99.107.109:2100', 'http://140.99.107.110:2100', 'http://140.99.107.111:2100', 'http://140.99.107.112:2100', 'http://140.99.107.113:2100', 'http://140.99.107.114:2100', 'http://140.99.107.115:2100', 'http://140.99.107.116:2100', 'http://140.99.107.117:2100', 'http://140.99.107.118:2100', 'http://140.99.107.119:2100', 'http://140.99.107.120:2100', 'http://140.99.107.121:2100', 'http://140.99.107.122:2100', ] class AvailableProxiesManager: _proxy_lock: threading.Lock = threading.Lock() def __init__(self): self._proxy_dict = dict.fromkeys(my_proxies, True) def get_proxy(self): """获取一个可用代理并标记为已占用""" proxy = None with self._proxy_lock: while not proxy: available = [p for p, is_available in self._proxy_dict.items() if is_available] if available: proxy = random.choice(available) self._proxy_dict[proxy] = False else: print('Waiting ... no proxies available') time.sleep(0.2) return proxy def release_proxy(self, proxy): """释放代理,标记为可用""" with self._proxy_lock: if proxy in self._proxy_dict: self._proxy_dict[proxy] = True print(f"Released proxy: {proxy}") available_proxies = AvailableProxiesManager() def main(): current_proxy = available_proxies.get_proxy() print(f"Thread {threading.get_ident()} acquired proxy: {current_proxy}") while True: try: response = requests.get('https://httpbin.org/ip', proxies={'https': current_proxy}, timeout=10) response.raise_for_status() print(f"Thread {threading.get_ident()} using proxy {current_proxy} - IP: {response.json()['origin']}") time.sleep(120) except requests.exceptions.RequestException as e: if isinstance(e, requests.exceptions.HTTPError) and e.response.status_code == 403: print(f"Thread {threading.get_ident()} got 403 for proxy {current_proxy}, switching to new proxy") # 释放旧代理 available_proxies.release_proxy(current_proxy) # 获取新代理 current_proxy = available_proxies.get_proxy() print(f"Thread {threading.get_ident()} acquired new proxy: {current_proxy}") else: # 处理其他请求异常(超时、连接错误等),可以选择重试或更换代理 print(f"Thread {threading.get_ident()} request failed with error: {str(e)}, retrying with same proxy...") time.sleep(10) if __name__ == '__main__': threads = [] for i in range(50): t = threading.Thread(target=main) threads.append(t) t.start() time.sleep(1)
关键改动说明
- 代理管理器调整:移除上下文管理器,新增
get_proxy和release_proxy方法,让线程主动控制代理的生命周期,只有当代理被403触发时才释放。 - 线程代理维护:每个线程启动时先获取一个代理并保存为
current_proxy,后续循环持续使用该代理,直到收到403响应才释放旧代理并获取新代理。 - 异常处理增强:捕获请求异常,区分403和其他错误(如超时),仅在403时更换代理,其他错误则重试当前代理。
内容的提问来源于stack exchange,提问作者WeInThis
相关产品推荐
相关产品推荐

