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

Python用requests并行发起站点GET请求校验3000用户名异常求解

问题原因排查
  • 异常处理逻辑有致命漏洞:请求抛出异常后,responses[username] 被赋值为字符串 'tgme_page_extra',后续直接调用.text属性会直接触发AttributeError,这是程序跑久后崩溃的核心原因之一
  • 无请求超时配置:requests.get 默认无超时限制,部分请求会无限挂起,导致线程资源被占满,后续请求全部阻塞
  • 线程模型不合理:3000个用户名对应创建3000个常驻线程,操作系统线程切换开销随运行时间上升会急剧增加,整体性能陡降
  • 代理侧并发无控制:单个代理同时承载50个线程的请求,高频请求下极易被目标站点限流、拉黑,返回异常响应
  • 连接无复用:每次请求都新建TCP连接,三次握手开销大,也更容易被站点的反爬策略识别
  • 共享变量无锁:全局responses字典被多线程同时读写,会出现竞态条件,导致存储的响应数据错乱
优化实现方案

采用ThreadPoolExecutor控制全局并发总量,每个代理绑定独立的requests.Session复用连接,限制单代理并发数,补全异常处理和超时配置,加锁保护共享变量,参考代码如下:

import requests
import time
import random
import config
from concurrent.futures import ThreadPoolExecutor
from threading import Lock

# 可根据实际情况调整的配置项
MAX_TOTAL_CONCURRENCY = 200 # 全局总并发数,匹配代理池总承载能力
MAX_PROXY_CONCURRENCY = 10 # 单代理最大并发数,避免单IP请求过频被封
REQUEST_TIMEOUT = 10 # 单请求最长等待时间,单位秒

# 全局共享变量加锁避免竞态
responses = {}
res_lock = Lock()

# 每个代理绑定独立Session复用TCP连接,降低握手开销
proxy_sessions = {}
for proxy in config.PROXY_LIST:
    session = requests.Session()
    session.headers.update(config.HEADERS)
    session.proxies = {"http": proxy, "https": proxy} # 可根据代理实际格式调整
    proxy_sessions[proxy] = session

# 用户名按代理分组,每组大小不超过单代理并发上限
username_groups = []
temp_group = []
for idx, username in enumerate(config.USERNAME_LIST):
    assigned_proxy = config.PROXY_LIST[idx % len(config.PROXY_LIST)]
    temp_group.append((username, assigned_proxy))
    if len(temp_group) == MAX_PROXY_CONCURRENCY:
        username_groups.append(temp_group)
        temp_group = []
if temp_group:
    username_groups.append(temp_group)

def check_username(username, proxy):
    session = proxy_sessions[proxy]
    current_text = None
    try:
        resp = session.get(config.URL + username, timeout=REQUEST_TIMEOUT)
        resp.raise_for_status() # 主动抛出4xx、5xx类响应异常
        current_text = resp.text
    except Exception as e:
        print(f"用户名{username}校验失败: {str(e)}")
        time.sleep(3)
        return
    
    # 写入全局变量前加锁
    with res_lock:
        responses[username] = current_text
    
    if "tgme_page_extra" not in current_text:
        # 用户名不可认领的对应业务逻辑
        pass
    else:
        # 其他业务逻辑
        pass

def run_single_check_cycle():
    with ThreadPoolExecutor(max_workers=MAX_TOTAL_CONCURRENCY) as executor:
        all_tasks = []
        for group in username_groups:
            for username, proxy in group:
                all_tasks.append(executor.submit(check_username, username, proxy))
        # 等待整轮所有校验任务完成
        for task in all_tasks:
            task.result()

if __name__ == "__main__":
    while True:
        run_single_check_cycle()
        # 整轮校验完成后统一休眠,控制整体请求频率
        time.sleep(random.choice(config.CHECK_INTERVAL))
额外优化建议
  • 可以根据代理返回的状态码(比如429、403)动态调整对应代理的并发数和冷却时间,遇到限流时自动降低该代理的请求频率
  • 如果后续校验量级继续提升,可以换用异步HTTP库aiohttp,并发性能会比线程池方案高30%以上
  • 可以增加代理可用性检测逻辑,遇到持续返回异常的代理自动从可用池中剔除,避免影响校验结果

内容的提问来源于stack exchange,提问作者Николай Добрыднев

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.30 18:30:05