爬虫任务动态代理ip+请求重试异常自愈代码示例详解,一篇就能跑通
关键词:python爬虫代理IP自动切换、高匿代理池搭建、requests重试装饰器、免费代理ip测试、反爬403自愈方案、爬虫超时异常处理、动态代理ip购买推荐
一、为什么你的爬虫总被封?
写完解析规则,跑了两页就403,再跑直接Timeout,八成是IP被拉黑。目标站点现在普遍上了“反爬套餐”:同IP请求频次>30次/5min就弹验证码,再狠点直接返回空数据。静态代理列表早就过时,只有“动态代理IP+自动重试+异常自愈”才能续命。
二、动态代理IP池到底长啥样?
别被“池”吓到,核心就三句话:
- 买接口→返回“代理IP:端口”json,比如http://api.xxx.com/get?num=10&type=1,每次掉用给10个高匿IP。
- 本地维护一个队列,爬虫线程每次pop一个IP,用完塞回尾部并记录耗时、失败次数。
- 失败>3次自动剔除,队列长度<5时触发补充。整个逻辑30行代码就能跑,后面直接给。
三、requests+Retry+自愈,代码直接搬
pip install requests retrying,复制下面这段,改两行就能用:
import requests, random, time, json
from retrying import retry
from queue import Queue
# 1. 动态拉代理
def fetch_ips():
api = 'http://api.xxx.com/get?num=20&type=1'
return [f"http://{ip}" for ip in requests.get(api, timeout=5).json()['data']]
# 2. 失败自动换IP
class ProxyPool:
def __init__(self):
self.q = Queue()
self._fill()
def _fill(self):
for ip in fetch_ips():
self.q.put({'ip': ip, 'fail': 0})
def get(self):
if self.q.qsize() < 5:
self._fill()
return self.q.get()
def feedback(self, proxy, ok):
if ok or proxy['fail'] >= 3:
return
proxy['fail'] += 1
self.q.put(proxy)
pool = ProxyPool()
# 3. 装饰器:超时+重试+自愈
@retry(stop_max_attempt_number=4, wait_fixed=2000)
def safe_get(url):
proxy = pool.get()
try:
r = requests.get(url, proxies={'http': proxy['ip'], 'https': proxy['ip']},
headers={'User-Agent': random.choice(UA_LIST)},
timeout=8)
if r.status_code == 200 and len(r.content) > 1000:
pool.feedback(proxy, True)
return r.text
else:
raise Exception('block')
except Exception as e:
pool.feedback(proxy, False)
raise e
# 4. 业务侧直接调
for page in range(1, 101):
html = safe_get(f'https://example.com/article?page={page}')
parse(html) # 你的解析函数
time.sleep(random.uniform(0.5, 1.5))
跑起来后,控制台会看到“fail→换IP→重试”循环,全程无人工,24h稳抓几千页数据。
四、免费代理能不能白嫖?
可以,但时间也是钱。免费代理平均可用率5%,还要自己写检测:
- 先往httpbin.org/ip发请求,回显IP与代理一致才算高匿;
- 再测访问目标站点,延迟>3s直接丢。
一套下来代码量翻倍,且随时失效,适合练手,真上线还是买动态代理IP省心,平均1~2分/次,成本远低于重新抓。
五、常见坑速查表
- https站点忘记加verify=False,直接SSLError。
- 代理返回空响应但status=200,记得加“内容长度”校验,防假200。
- retrying装饰器默认只在函数抛异常时才重试,想对特定状态码重写得自己raise。
- 多线程场景下Queue要加锁,或者直接用线程安全的queue.Queue,别用list.pop。
六、把代码做成微服务
如果公司级项目,建议把代理池独立成Flask服务:/get_proxy返回一个最佳IP,/report反馈失败次数,爬虫端只负责调用,逻辑解耦,后续换语言也不折腾。
七、动态代理IP购买避坑
看三点:
- 是否支持“每次请求换IP”,而不是固定5分钟才变;
- 有没有白名单+账密双重鉴权,方便本地和云函数同时跑;
- 是否给响应时间<2s的SLA,不然再便宜也白搭。
采购代理IP请添加微信客户经理:x31471626
评论0