Python 爬虫用代理 IP 的 6 个实用技巧(附代码示例)

11 阅读1分钟

Python 爬虫用代理 IP 的 6 个实用技巧(附代码示例)

做 Python 爬虫开发,代理 IP 是绕不开的话题。我在爬虫项目里踩过不少代理坑,总结出这6个实用技巧,附带可直接复用的代码示例。

技巧一:用 httpbin 验证代理可用性

在把代理投入生产环境之前,先用 httpbin 做一轮快速验证。httpbin.org 会原样返回你的请求信息,非常适合用来检查代理是否生效。

import requests

def test_proxy(proxy_url):
    """验证代理是否可用"""
    proxies = {"http": proxy_url, "https": proxy_url}
    try:
        resp = requests.get("https://httpbin.org/ip", proxies=proxies, timeout=10)
        if resp.status_code == 200:
            ip = resp.json().get("origin", "unknown")
            print(f"代理可用,出口IP: {ip}")
            return True
    except Exception as e:
        print(f"代理不可用: {e}")
    return False

# 使用示例
test_proxy("http://username:password@proxy-host:port")

这个函数有两个作用:一是确认代理能正常转发请求,二是查看代理的出口 IP 地址,验证是否符合预期的地域。

技巧二:设置合理的超时和重试策略

代理请求的响应时间波动较大,超时设置过短会导致大量误判,过长又会拖慢整体进度。

import requests
from requests.adapters import HTTPAdapter
from urllib3.util.retry import Retry

session = requests.Session()

# 配置重试策略
retry = Retry(
    total=3,
    backoff_factor=1,  # 重试间隔: 1s, 2s, 4s
    status_forcelist=[429, 500, 502, 503, 504],
    allowed_methods=["GET", "POST"]
)

adapter = HTTPAdapter(max_retries=retry)
session.mount("http://", adapter)
session.mount("https://", adapter)

# 设置超时:连接5秒,读取15秒
response = session.get(
    "https://target-site.com/data",
    proxies={"http": proxy_url, "https": proxy_url},
    timeout=(5, 15)
)

这里的超时用了元组格式 (connect_timeout, read_timeout),分别控制连接建立和数据读取的超时时间。重试策略针对服务器错误和限流状态码自动重试,避免因为偶发问题丢弃有效代理。

技巧三:Scrapy 中优雅集成隧道代理

Scrapy 的代理配置比 requests 稍微复杂一些,但用对方法后非常省心。

settings.py 中配置:

# 隧道代理配置
PROXY_URL = "http://username:password@tunnel.wukongdaili.com:port"

DOWNLOADER_MIDDLEWARES = {
    'scrapy.downloadermiddlewares.httpproxy.HttpProxyMiddleware': 100,
}

# 在 spider 中设置代理
class MySpider(scrapy.Spider):
    name = "example"
    
    def start_requests(self):
        for url in self.start_urls:
            yield scrapy.Request(
                url,
                meta={'proxy': PROXY_URL},
                callback=self.parse
            )

如果用的是隧道代理,每次请求 Scrapy 会自动通过隧道服务器获取新的出口 IP,无需手动轮换。

技巧四:用 aiohttp 做高并发代理请求

当采集量达到万级时,同步请求的效率瓶颈会非常明显。aiohttp 的异步能力可以把代理请求的吞吐量提升一个数量级。

import aiohttp
import asyncio

async def fetch_with_proxy(session, url, proxy):
    try:
        async with session.get(url, proxy=proxy, timeout=aiohttp.ClientTimeout(total=15)) as resp:
            return await resp.text()
    except Exception as e:
        return f"Error: {e}"

async def main():
    proxy = "http://username:password@proxy-host:port"
    urls = ["https://httpbin.org/ip"] * 10  # 模拟10个并发请求
    
    async with aiohttp.ClientSession() as session:
        tasks = [fetch_with_proxy(session, url, proxy) for url in urls]
        results = await asyncio.gather(*tasks)
        for i, result in enumerate(results):
            print(f"请求 {i+1}: {result[:100]}...")

asyncio.run(main())

并发数不是越高越好,需要根据代理服务商的并发上限和目标网站的承载能力做调整。建议从 20-50 并发开始逐步测试。

技巧五:建立代理 IP 质量监控

在生产环境中,代理 IP 的质量会随时间波动。建立一个简单的监控机制,可以及时发现问题。

import time
import statistics

class ProxyMonitor:
    def __init__(self, proxy_url):
        self.proxy_url = proxy_url
        self.response_times = []
        self.success_count = 0
        self.total_count = 0
    
    def check(self):
        """单次健康检查"""
        start = time.time()
        try:
            resp = requests.get(
                "https://httpbin.org/ip",
                proxies={"http": self.proxy_url, "https": self.proxy_url},
                timeout=10
            )
            elapsed = time.time() - start
            self.response_times.append(elapsed)
            self.success_count += 1
            return resp.status_code == 200
        except Exception:
            return False
        finally:
            self.total_count += 1
    
    def get_stats(self):
        """返回统计数据"""
        success_rate = self.success_count / self.total_count if self.total_count else 0
        avg_time = statistics.mean(self.response_times) if self.response_times else 0
        return {
            "success_rate": f"{success_rate:.1%}",
            "avg_response": f"{avg_time:.2f}s",
            "total_requests": self.total_count
        }

建议每 100 次请求做一次健康检查,如果成功率低于 90% 或平均响应时间超过 3 秒,考虑切换代理供应商。

技巧六:处理代理认证和特殊协议

有些代理服务需要用户名密码认证,有些只支持 HTTP,有些支持 SOCKS5。认证方式不对是最常见的"代理用不了"的原因。

# HTTP 代理认证(用户名密码在 URL 中)
proxy_auth = "http://user:pass@proxy-host:port"

# 使用 requests 的代理认证参数
proxy_host = "http://proxy-host:port"
auth = ("user", "pass")

response = requests.get(
    "https://target-site.com",
    proxies={"http": proxy_host, "https": proxy_host},
    auth=auth,
    timeout=10
)

# SOCKS5 代理(需要安装 requests[socks])
# pip install requests[socks]
socks_proxy = "socks5://user:pass@proxy-host:port"
response = requests.get("https://target-site.com", proxies={"http": socks_proxy, "https": socks_proxy})

进阶建议:何时该从免费代理升级到付费代理

如果你正在用免费代理做项目,遇到以下情况说明该升级了:

成功率低于 70%,说明免费代理的可用率太低(通常在 30%-60%),大量时间浪费在重试上。响应时间超过 5 秒的慢代理不仅拖慢采集进度,还可能触发目标网站的超时封禁。IP 被频繁封禁意味着代理的 IP 被多人共用,早就上了目标网站的黑名单。当项目从实验走向生产,稳定的 SLA 保障就成为刚需。

付费代理服务如 悟空代理的隧道代理独享代理 IP 方案,提供高可用率的 IP 资源和完善的技术支持,可以把代理相关的故障时间减少 90% 以上。

写在最后

代理 IP 不是配上去就完了的事。合理的超时重试、健康监控、并发控制,才是保证爬虫稳定运行的关键。把这 6 个技巧用到你的项目里,代理相关的故障率会明显下降。

如果你的项目正面临代理不稳定、IP 被封、并发不够等问题,可以了解一下 悟空代理 的解决方案,覆盖隧道代理、独享代理、住宅代理等多条产品线,快速解决你的代理难题。