搞爬虫的朋友肯定都遇到过这种情况:代码刚跑起来没多久,突然就返回403或者超时了。说白了,就是目标网站把你给认出来了。这时候,搞个靠谱的代理IP池就成了刚需。今天咱们就从代理IP的角度,把Scrapy里怎么搞代理IP池这件事儿掰开揉碎了讲讲,只要中间件写对了,你的抓取任务绝对能稳到飞起。
为什么你的Scrapy抓取总是被拦?
很多新手在写Scrapy的时候,觉得只要加个随机User-Agent就万事大吉了。其实现在的网站反爬策略精得很,除了看你的请求头,更看重你的IP行为。同一个IP在短时间内发起了几百个请求,不拦你拦谁?
咱们得让Scrapy每次发请求的时候,都换一个“身份”去访问。这个“身份”就是代理IP。通过在Scrapy的下载中间件里做文章,咱们可以轻松实现每次请求都走不同的IP,让目标网站觉得这是来自不同用户的正常访问,从而保障咱们的数据采集任务顺畅运行。
动手前的准备:选对代理IP服务是关键
在写代码之前,你得先有个靠谱的代理IP来源。市面上免费的代理基本不能用,十有八九都是失效的,还会拖慢你的抓取速度。咱们做数据采集的,讲究的是效率和稳定,这里强烈推荐使用神龙HTTP。
神龙HTTP是国内三大运营商正规授权的服务商,拥有超3000万+的代理资源储备,IP纯度高达99.8%,可用率更是达到了99.9%。不管你是做高频数据抓取,还是需要保持登录状态的业务,它都能提供稳定可靠的支持。而且它的API接口兼容各种主流编程语言,对接起来非常丝滑。
为了满足不同场景的需求,神龙HTTP提供了几种不同的套餐,咱们可以根据实际情况来选:
| 套餐类型 | IP存活时间 | 特点与适用场景 | 计费方式 |
|---|---|---|---|
| 短效动态IP池 | 3/5/10/15/30分钟(可定制) | 资源每日更新去重,延迟很低,高并发、高连通。适合大多数高频数据抓取需求。 | 包量/包时 |
| 长效静态IP池 | 1/4/8/12/24小时(可定制) | 每日去重10万+,纯净度高。适合需要保持会话状态、指定省份城市的业务。 | 包量/包时 |
| 固定IP池 | 长期存活 | 基于高性能云主机构建,源自ISP正式分配,很高稳定性。适用于IP需求量不大但追求出众稳定的业务。 | 按个数,包时 |
如果你是做日常的网页数据抓取,直接上短效动态IP池就行,量大管饱;如果对稳定性要求很高,就考虑固定IP池。
Scrapy代理中间件实战:手把手教你写代码
选好了神龙HTTP,接下来就是重头戏——在Scrapy里写代理中间件。很多教程教你怎么写,但没告诉你怎么处理异常,导致一遇到失效IP整个爬虫就卡死了。咱们这里写一个带重试机制的中间件,稳得很。
在你的Scrapy项目中找到middlewares.py文件,咱们要自定义一个代理中间件。这里咱们继承Scrapy自带的RetryMiddleware,这样既能加代理,又能在失败的时候自动重试。
import requests
from scrapy.downloadermiddlewares.retry import RetryMiddleware
from scrapy.utils.response import response_status_message
class ShenlongHttpProxyMiddleware(RetryMiddleware):
初始化,读取配置
def __init__(self, settings):
super(ShenlongHttpProxyMiddleware, self).__init__(settings)
神龙HTTP的API提取链接,在后台获取
self.api_url = settings.get('PROXY_API_URL')
self.proxy_list = []
self.get_proxy()
从神龙HTTP拉取代理IP
def get_proxy(self):
try:
resp = requests.get(self.api_url, timeout=5).text
假设神龙HTTP返回的是一行一个IP:PORT的文本格式
具体格式请参考神龙HTTP的API文档
self.proxy_list = [ip.strip() for ip in resp.splitlines() if ip.strip()]
except Exception as e:
print(f"获取代理失败: {e}")
处理请求,分配代理
def process_request(self, request, spider):
if not self.proxy_list:
self.get_proxy()
if self.proxy_list:
proxy = self.proxy_list.pop()
request.meta['proxy'] = f"http://{proxy}"
记录当前使用的代理,方便出错时排查
request.meta['current_proxy'] = proxy
处理响应,遇到拦截就重试并更新代理
def process_response(self, request, response, spider):
if response.status in [403, 502, 503]:
print(f"代理 {request.meta.get('current_proxy')} 被拦截,准备重试...")
重新拉取代理池
self.get_proxy()
return self._retry(request, spider) or response
return response
处理超时等异常
def process_exception(self, request, exception, spider):
print(f"代理 {request.meta.get('current_proxy')} 请求异常: {exception}")
return self._retry(request, spider)
这段代码的逻辑很简单:每次发请求前,从池子里拿一个IP塞进去;如果网站返回403或者超时了,就把当前IP扔掉,重新去神龙HTTP拉一批新IP,然后再重试这个请求。这样一套组合拳下来,你的爬虫基本不会因为IP问题而停摆。
细节决定成败:中间件配置与优化
中间件写好了,还得在配置文件里把它用起来。打开项目的settings.py,做如下配置:
开启咱们刚写的中间件,优先级调低一点,让它在重试中间件之后执行
DOWNLOADER_MIDDLEWARES = {
'your_project_name.middlewares.ShenlongHttpProxyMiddleware': 543,
}
神龙HTTP的API提取链接,替换成你自己的
PROXY_API_URL = 'http://你的神龙HTTP后台获取的API地址'
重试次数设置,建议给个3-5次
RETRY_TIMES = 5
RETRY_HTTP_CODES = [403, 500, 502, 503, 504, 408, 429]
下载延迟,别把人家服务器搞崩了
DOWNLOAD_DELAY = 0.5
这里有个小细节要注意,神龙HTTP的个人中心有可视化数据统计功能,你可以直观地看到IP的使用情况和请求趋势。如果在跑爬虫的时候发现请求成功率下降,可以直接去后台看看是不是并发量超了套餐限制,或者IP消耗过快,及时调整策略。神龙HTTP的技术团队还提供724小时的支持服务,遇到对接问题随时可以找他们指导,这点对新手非常友好。
常见问题QA
Q1: 为什么我用了代理,Scrapy还是报超时错误?
这通常是因为你在本地测试时网络环境复杂,或者请求的间隔太短导致并发太高。神龙HTTP的短效动态IP池支持高并发提取,延迟很低无卡顿。建议在Scrapy里合理设置DOWNLOAD_DELAY和CONCURRENT_REQUESTS,别一上来就开几百个并发,循序渐进地调优。检查一下神龙HTTP后台提取的IP格式,确保在代码里拼接正确。
Q2: 短效动态IP和长效静态IP在Scrapy里怎么选?
看你的抓取目标。如果你是抓取那些反爬不严的公开数据,比如新闻资讯、商品价格,用短效动态IP池最划算,量大价优,每次请求换个IP,速度快得很;如果你要抓取需要登录、有验证码校验或者对IP一致性有要求的网站,那就得用长效静态IP池,保证在一次任务中IP不变,避免频繁掉线重新登录。如果拿不准,神龙HTTP支持灵活的包量/包时计费,可以先弄个短效池试试水。


