写爬虫的时候,大家肯定都遇到过这种情况:代码刚跑起来没几分钟,就疯狂报错403,或者直接连接超时。其实这多半是因为你本机IP被目标网站封了。网站的反爬策略现在都很精明,同一个IP短时间内请求次数一多,直接就给你拉黑了。想解决这个问题,最直接的办法就是在请求的时候挂上代理IP,并且让程序在遇到问题的时候自动换IP重试。今天咱们就来聊聊怎么把这个过程自动化,顺便手把手封装一个带重试机制的requests请求类。
为什么爬虫需要自动更换代理IP?
很多新手刚开始写爬虫的时候,喜欢用一个IP死磕,被封了就手动重启路由器换IP,或者干脆等个几小时再跑。这种方法对付小打小闹的采集还行,如果是正经做业务数据抓取,效率低得让人抓狂。
自动更换代理IP的核心目的就是为了保持爬虫的高效运转。当目标服务器发现某个IP行为异常时,会切断连接。如果我们的程序能敏锐地察觉到这一点,立刻丢弃这个失效的IP,从代理IP池里拿一个新的顶上,重新发起请求,那爬虫的连续性就能得到保障。这就好比打游击战,打一枪换一个地方,不让对方摸清我们的真实底细。
如何获取并自动更换天启代理IP?
要实现自动更换,首先得有一个源源不断提供IP的源头。这里推荐使用天启代理。作为企业级代理IP服务商,天启代理拿的是运营商正规授权的资源,自建机房网络非常纯净,而且支持HTTP/HTTPS/SOCKS5三大协议,不管你的爬虫是基于什么框架写的,都能无缝接入。
自动更换的逻辑其实很简单:我们通过天启代理提供的API接口,提前批量拉取一批IP到本地内存里,或者每次请求前动态去API拿一个。天启代理的接口请求时间不到1秒,响应延迟≤10毫秒,所以动态获取完全不会拖慢爬虫的整体速度。当程序检测到当前请求失败(比如返回状态码非200或者抛出超时异常),我们就调用一个换IP的方法,把当前请求用的代理替换成天启代理的新IP,然后再试一次。
手把手封装带重试机制的requests请求类
光说不练假把式,下面咱们直接写代码。我们用Python的requests库为基础,封装一个专门的请求类。这个类要干两件事:第一,每次请求自动带上天启代理的IP;第二,遇到报错或者状态码不对,自动换一个新的代理IP重试。
在写代码之前,我们需要用到天启代理的API链接。天启代理支持丰富的API参数自定义,你可以设置返回IP的格式、数量等。我们假设你已经拿到了这个API链接。
下面是具体的代码实现:
import requests
import time
from requests.exceptions import RequestException
class TianqiProxyRequest:
def __init__(self, api_url, max_retries=3):
self.api_url = api_url 天启代理的API提取链接
self.max_retries = max_retries 最大重试次数
self.session = requests.Session()
self.current_proxy = self._get_new_proxy() 初始化时拿一个新IP
def _get_new_proxy(self):
"""通过天启代理API获取新的代理IP"""
try:
resp = requests.get(self.api_url, timeout=5)
if resp.status_code == 200:
假设天启API返回的格式是 ip:port
ip_port = resp.text.strip()
return {"http": f"http://{ip_port}", "https": f"http://{ip_port}"}
except Exception as e:
print(f"获取代理IP失败: {e}")
return None
def request(self, url, method="GET", kwargs):
"""带重试机制的请求方法"""
for attempt in range(1, self.max_retries + 1):
if not self.current_proxy:
print("当前无可用代理,正在重新获取...")
self.current_proxy = self._get_new_proxy()
if not self.current_proxy:
time.sleep(2) 获取不到就等一会儿
continue
try:
设置请求超时时间,天启代理响应极快,设置10秒足够了
response = self.session.request(method, url, proxies=self.current_proxy, timeout=10, kwargs)
如果状态码正常,直接返回结果
if response.status_code == 200:
return response
else:
print(f"请求失败,状态码: {response.status_code},准备换IP重试...")
except RequestException as e:
print(f"请求发生异常: {e},准备换IP重试...")
走到这里说明请求失败了,需要更换IP
self.current_proxy = self._get_new_proxy()
print(f"达到最大重试次数 {self.max_retries},请求失败。")
return None
这段代码的逻辑非常直白:初始化的时候先拿一个IP。发起请求时,如果遇到任何异常或者状态码不是200,程序就会自动去天启代理的API拿一个新的IP,覆盖掉旧的IP,然后进入下一次循环重试。直到达到你设置的最大重试次数为止。
天启代理在爬虫实战中的优势
为什么在这个封装类里推荐用天启代理?因为爬虫跑起来对IP的质量要求极高。如果代理本身响应就慢吞吞的,重试机制再好也没用。天启代理的IP可用率≥99%,这意味着你通过API拿到的IP,基本拿来就能用,不会刚拿到手就是个死IP。天启代理支持资源自由去重,支持24小时自动去重和按需过滤,这样我们在批量拉取IP的时候,就不用自己写代码去过滤重复的IP了,大大减轻了爬虫的负担。
为了更直观地展示天启代理的核心参数,我整理了一个表格:
| 功能/参数 | 天启代理表现 | 对爬虫的实际帮助 |
|---|---|---|
| 协议支持 | HTTP/HTTPS/SOCKS5 | 适配各类爬虫框架,requests、scrapy等都能无缝接入 |
| 节点覆盖 | 全国200+城市自建机房 | IP来源纯净,一手机房资源,不易被目标网站识别封杀 |
| 响应速度 | 延迟≤10毫秒,接口请求<1秒 | 配合重试机制,换IP过程极快,不拖慢整体采集效率 |
| 高并发支持 | 分布式集群架构,支持高并发 | 多线程、协程爬虫同时请求时,IP服务不会崩溃 |
| 授权方式 | 终端IP授权、账号密码授权 | 灵活绑定,避免IP被盗用,保障采集任务安全 |
常见问题QA模块
Q1:重试次数设置多少比较合适?
设置3到5次就足够了。天启代理的IP可用率很高,如果重试3次还失败,大概率不是IP本身的问题,可能是目标网站服务器临时波动,或者你的网络请求参数被识别了。盲目增加重试次数反而会拖慢爬虫的整体进度。
Q2:为什么用了代理IP,程序还是会偶尔报超时?
网络请求本身就有不确定性,目标网站的服务器如果刚好在那几秒钟负载过高,也会导致超时。这时候我们封装的重试机制就派上用场了,遇到超时直接换一个天启代理的新IP重试,通常第二次就能顺利拿到数据。
Q3:多线程跑爬虫的时候,这个类该怎么用?
在多线程环境下,不要让多个线程共用同一个请求类实例。最好的做法是每个线程维护自己的请求类实例,或者把获取IP和请求的逻辑做一层线程隔离。天启代理支持高并发调用,底层是分布式集群架构,所以API接口端完全扛得住多线程的频繁拉取。
Q4:API提取IP的时候,需不需要自己写代码去重?
不需要额外写代码。天启代理本身就提供了多种去重模式,支持24小时自动去重。你在配置API参数的时候,直接把去重选项勾上,拿到的IP就不会有重复的,省时省力。

