本期学习:代理的使用与代理池的更新
1 代理IP提取
在Scrapy 爬取旅游景点相关数据(六)已经讲到了代理的使用,可以先学习这一期再来看本期内容,
第一步是代理IP提取,下面代码就是在中间件初始化的时候去更新代理池,后面这个2是一次更新的代理服务器的数量,可以看到,代理池是一个列表:
python
class ProxyMiddleware:
def __init__(self):
self.proxies = [] #代理池
self.user = '***'
self.passw = '***'
self.update_proxies() #初始化的时候更新代理池
self.logger = logging.getLogger(__name__)
def update_proxies(self):
self.proxies = get_proxy(self.user, 2) #这个方法要根据你使用的代理服务自己定制
2 代理使用
使用方式很简单,就是在process_request里加到request.meta里面,注意到,这边先判断了代理池是否是空的,如果是空的,也会触发更新代理池的操作。
python
def process_request(self, request, spider):
if not self.proxies:
self.update_proxies()
proxy = random.choice(self.proxies)
# print(f"目前使用的代理是:http://{proxy}")
request.meta['proxy'] = f"http://{self.user}:{self.passw}@{proxy}"
user_agent_list = [
....
]
request.headers['User-Agent'] = random.choice(user_agent_list)
3 异常处理
代理服务器可能存在问题,比如生命期过了,或者被目标网站禁掉了,所以必须要增加异常处理机制,这边特别要说的是这个 TunnelError ,我使用的代理在服务器过期的情况下会抛这个异常,所以异常处理里面需要处理的异常要根据自己的实际情况来写写,下面代码只是给一个参考:
python
# 如果请求过程中发生异常(如网络错误或连接错误),process_exception 方法被调用。
def process_exception(self, request, exception, spider):
self.logger.error(f'请求过程中发生异常{type(exception).__name__}' )
if isinstance(exception, (MaxRetryError, ConnectionError, TunnelError,
ConnectionRefusedError, ResponseNeverReceived)):
self.logger.warning('出现连接异常,清除代理..')
self.logger.warning(request.meta.get('proxy'))
self.remove_proxy(request.meta.get('proxy'))
return self.retry_request(request)
return request
# 是否要根据异常删除代理池中的代理,也请根据实际测试下来的结果加以修改
def remove_proxy(self, proxy):
ip_port = proxy.replace("http://", "")
self.logger.warning(f'删除代理: {ip_port}')
self.logger.info(self.proxies)
self.proxies = [p for p in self.proxies if f"{p}" != ip_port]
self.logger.info(self.proxies)
# 重试
def retry_request(self, request):
if not self.proxies:
self.update_proxies()
proxy = random.choice(self.proxies)
self.logger.info(f"重试,目前使用的代理是: http://{proxy}")
self.logger.info(self.proxies)
request.meta['proxy'] = f"http://{self.user}:{self.passw}@{proxy}"
user_agent_list = [
...
]
request.headers['User-Agent'] = random.choice(user_agent_list)
return request
remove_proxy 会删除指定的代理地址
retry_request 会重发请求
4 测试
小结
开发爬虫是一个非常考验耐心和细心的工作,需要投入大量时间研究,如果对其他内容感兴趣可以去我的专栏,里面还有其他【项目实战】文章。