前言:
项目完成后,你要通过scrapy进行抓取;现在问题是,如果你还是用之前调好的延时爬取,你没必要用scrapy呀!那你这是什么效率,2-3秒抓一个url.疯了?
所以,这时候,我们需要给他装个ip_pool ; 没有它,你玩啥爬虫~爬蜗牛了就是;
正文:
抓ip的文章,我写在前面了
拿到这些ip,存哪是你自己的事;我个人建议是存redis,因为他最快;
然后,ip的代理业务写在哪里呢? scrapy的中间件
我个人是希望重新开一个类,专门给他定义成代理ip的类:
import redis
import random
import time
class ProxyMiddleware:
def __init__(self):
self.redis_client = redis.Redis()
self.ip_cache = []
def process_request(self, request, spider):
# 从缓存中获取一个代理IP,并设置为请求的代理
proxy_ip = self.get_proxy_ip()
request.meta['proxy'] = proxy_ip
def process_response(self, request, response, spider):
# 处理响应,若状态码为403或429,则移除请求所使用的代理IP
if response.status in [403, 429]:
self.remove_proxy_ip(request.meta['proxy'])
return response
def process_exception(self, request, exception, spider):
# 处理异常,将请求所使用的代理IP从缓存中移除
self.remove_proxy_ip(request.meta.get('proxy'))
return None
def get_proxy_ip(self):
# 若IP缓存数量少于10个,则刷新缓存,获取新的代理IP
if len(self.ip_cache) < 10:
self.refresh_proxy_ips()
return self.ip_cache.pop()
def refresh_proxy_ips(self):
# 若IP缓存数量少于10个,则从Redis获取新的代理IP,并加入缓存
if len(self.ip_cache) < 10:
proxy_ips = self.redis_client.smembers('ippool')
for ip in proxy_ips:
self.ip_cache.append(ip.decode())
def remove_proxy_ip(self, proxy_ip):
# 从缓存中移除指定的代理IP
if proxy_ip in self.ip_cache:
self.ip_cache.remove(proxy_ip)
def start_requests(self):
# 启动爬虫时,若IP缓存数量少于10个,则循环刷新缓存,直到达到10个IP为止
while len(self.ip_cache) < 10:
self.refresh_proxy_ips()
if len(self.ip_cache) < 10:
time.sleep(30)
1.首先,你不能每爬一个url,就去redis里面拿一个;要是这样,你scrapy是异步抓取的,光拿ip对redis的请求就足够让你的程序爆了;
2.把ip全部放在scrapy内部缓存里面,这样提速,几十个 几百个ip,足够玩一阵子;
3.当scrapy发起请求,就拿一个ip,如果返回来的response.state有问题,就换一个ip再来一次;同时,在缓存里面,把这个失效(无用的ip)删掉;
4.当你缓存的ip少于X的时候,就再去redis里面拿ip;
5.如果redis里面的ip供应不过来,就让他等待一阵子再去拿;
--------------基本思路就是如此!