You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何让线程持续使用同一代理直至返回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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.09 18:55:12