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

爬取链接时代理连接失败,如何重试当前循环?

处理爬虫代理连接失败的解决方案

嘿,这个问题我之前做大规模数据爬取的时候可太熟悉了!代理不稳定简直是爬虫的噩梦,直接让程序崩掉前功尽弃太闹心。咱们一步步来解决这个问题:

核心思路:别让单次失败终止整个程序

首先,你的程序之所以直接关闭,是因为没捕获代理连接失败的异常,Python默认会把未捕获的异常抛出来终止程序。所以第一步必须把异常接住,然后决定是重试还是换代理。

至于你问的「持续尝试代理连接直至成功」还是「重新运行当前循环」——其实最优解是两者结合:先对当前代理重试几次(避免临时网络波动导致的失败),如果还是不行,就换一个代理重新尝试当前URL的爬取;要是代理池里的代理都试过了还失败,就把这个URL记录下来,后续再处理,绝对不能直接终止整个程序。

具体实现代码示例

我以Python的requests库为例,给你写个可落地的版本,用到了tenacity这个重试库(需要先pip install tenacity):

import requests
import random
import logging
from tenacity import retry, stop_after_attempt, wait_exponential, retry_if_exception_type

# 配置日志,方便排查问题
logging.basicConfig(level=logging.INFO, format="%(asctime)s - %(levelname)s - %(message)s")
logger = logging.getLogger(__name__)

# 你的代理池(建议定期检测代理可用性,剔除失效的)
PROXY_POOL = [
    "http://proxy1:8080",
    "http://proxy2:8080",
    "http://proxy3:8080",
    # 更多代理...
]

# 待爬取的链接列表
URLS_TO_CRAWL = [
    "https://target-url-1.com",
    "https://target-url-2.com",
    # 更多链接...
]

# 定义重试逻辑:针对代理错误/连接错误,重试3次,等待时间指数增长
@retry(
    stop=stop_after_attempt(3),  # 最多重试3次
    wait=wait_exponential(multiplier=1, min=2, max=10),  # 等待时间:2s→4s→8s(不超过10s)
    retry=retry_if_exception_type((requests.exceptions.ProxyError, requests.exceptions.ConnectionError))
)
def fetch_url(url, proxy):
    """用指定代理爬取单个URL"""
    logger.info(f"尝试用代理 {proxy} 爬取 {url}")
    response = requests.get(
        url,
        proxies={"http": proxy, "https": proxy},
        timeout=15,  # 设置超时,避免程序卡住
        headers={"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36"}
    )
    response.raise_for_status()  # 抛出HTTP状态码异常(比如403、500)
    return response

def main():
    for url in URLS_TO_CRAWL:
        success = False
        used_proxies = set()  # 记录已经试过的代理,避免重复踩坑
        max_proxy_attempts = len(PROXY_POOL)  # 最多尝试所有代理一次

        while not success and len(used_proxies) < max_proxy_attempts:
            current_proxy = random.choice(PROXY_POOL)
            if current_proxy in used_proxies:
                continue
            used_proxies.add(current_proxy)

            try:
                response = fetch_url(url, current_proxy)
                # 这里写你的数据处理逻辑:解析HTML、保存到数据库/文件等
                logger.info(f"✅ 成功爬取 {url},状态码:{response.status_code}")
                success = True

            except requests.exceptions.ProxyError:
                logger.warning(f"❌ 代理 {current_proxy} 连接失败,换代理重试...")
            except requests.exceptions.ConnectionError:
                logger.warning(f"❌ 连接 {url} 超时,换代理重试...")
            except requests.exceptions.HTTPError as e:
                logger.error(f"❌ 爬取 {url} 遇到HTTP错误:{str(e)},标记为待处理")
                break
            except Exception as e:
                logger.error(f"❌ 爬取 {url} 遇到未知错误:{str(e)},标记为待处理")
                break

        if not success:
            # 所有代理都试过还失败,记录到文件或者数据库
            with open("failed_urls.txt", "a", encoding="utf-8") as f:
                f.write(f"{url}\n")
            logger.error(f"⚠️ 所有代理都无法爬取 {url},已记录到failed_urls.txt")

if __name__ == "__main__":
    main()

关键细节解释

  1. 异常捕获:专门针对ProxyError和ConnectionError做处理,这是代理连接失败最常见的两种异常;同时也捕获其他HTTP错误和未知异常,避免程序崩溃。
  2. 重试机制:用tenacity的装饰器实现智能重试,指数增长的等待时间能降低被目标网站封禁的风险,也给代理恢复的时间。
  3. 代理池轮换:每个URL会尝试不同的代理,直到成功或者代理池用完,避免死磕一个失效的代理。
  4. 失败记录:把爬取失败的URL记录下来,后续可以换一批代理再重新爬,不会丢失任务。

额外建议

  • 维护代理池:定期检测代理的可用性(比如定时请求百度,看能不能成功),把失效的代理从池子里删掉,补充新的有效代理,这能大幅减少连接失败的概率。
  • 不要无限重试:设置重试次数上限,比如最多重试3次代理,最多尝试5个不同的代理,避免陷入死循环。
  • 模拟真实请求:加上合理的User-Agent,甚至可以随机切换,避免被目标网站识别为爬虫。

内容的提问来源于stack exchange,提问作者phapha pha

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.19 07:33:50