代理IP池应存为字典结构,含http/https双协议配置、last_used和fail_count字段;禁用set去重;本地缓存用JSON文件;需同步测试HTTP/HTTPS且超时≤3秒;采用双缓冲机制(active_pool/pending_pool)配合原子替换与线程锁。

代理IP池该用什么结构存
用列表存原始IP字符串,运行时会频繁出错——比如没带端口、协议缺失、超时格式不统一。实际要存成字典,每个IP附带http和https两套配置,加上last_used和fail_count字段,方便后续淘汰逻辑介入。
常见错误现象:requests.exceptions.ProxyError 或 ConnectTimeout 频发,但日志里看不出是哪个IP挂了——因为没做来源标记。
- 结构示例:
{"proxy": "http://user:pass@1.2.3.4:8080", "http": "http://...", "https": "https://...", "last_used": 1717023456, "fail_count": 0} - 别用
set去重IP:相同IP不同认证参数(如不同用户名)应视为不同代理 - 本地缓存建议用
json文件而非内存变量,否则脚本重启后IP池清零
怎么判断一个代理是否可用
不能只靠requests.get("http://httpbin.org/ip", proxies=...)——很多免费代理能通HTTP但不支持HTTPS,而目标网站强制跳转HTTPS时就直接失败。
必须同时测http和https两个协议,且超时设为3秒以内,否则单个坏IP拖慢整个池的刷新节奏。
立即学习“Python免费学习笔记(深入)”;
让 macOS 自动化像说话一样简单 —— 用代码控制你的 Mac,无需学习 AppleScript 系统要求 macOS 14+ (Sonoma) Python 3.9+ 需要开启:辅助功能 + 屏幕录制权限
- 测试URL优先选
http://httpbin.org/get(返回JSON,结构稳定)和https://httpbin.org/get - 检查响应状态码+是否含
"origin"字段,避免返回HTML页面或防火墙拦截页 - 连续3次失败就
fail_count += 1,≥5次直接从池中移除,别等它“自愈”
动态更新IP池时如何不中断爬虫
边爬边换IP不是加个time.sleep(1)就能解决的——新IP还没验证完,旧IP已失效,中间出现空窗期,请求直接抛ProxyError。
得用双缓冲机制:始终维护active_pool和pending_pool两个列表,后台线程异步填充pending_pool,验证通过后原子替换。
- 替换时机:仅在
len(pending_pool) > len(active_pool) * 0.3时才切换,避免频繁抖动 - 替换操作必须用
threading.Lock保护,否则多线程取代理时可能拿到空列表 - 不要在每次请求前都查池大小——用
random.choice(active_pool)前先if not active_pool:fallback到等待逻辑
哪些代理源实际可用且适合自动化抓取
公开免费代理站(如free-proxy-list.net)的HTML结构隔三差五改,XPath一崩就是半天;而付费API(如proxyapi.io)返回JSON稳定,但rate_limit_exceeded错误没处理好就会卡死。
真正能跑通的组合是:国内用快代理的开放API(需注册拿orderid),国外用ScraperAPI的render=true参数兜底JS渲染站点。
- 快代理接口示例:
https://dps.kdlapi.com/api/getdps/?orderid=xxx&num=20&sep=1,注意sep=1返回换行分隔,需手动split - 别信“永久免费高匿IP”——99%会在第3次请求后返回
403或空响应体 - 所有代理源必须加
try/except包裹,捕获requests.exceptions.RequestException,失败就跳过,不抛异常
IP池真正的难点不在获取,而在“什么时候该信它”。一个代理通过了三次测试,不代表第四次不会丢包;一个IP刚被踢出池,下分钟可能又活了。所以验证逻辑得轻量、可插拔,别把它写进核心调度层。

















