我通过覆盖RetryMiddleware在Scrapy中创建了一个自定义中间件,它在重试之前更改了Proxy和User-Agent。看起来像这样
} catch (IOException | ParseException e1) {
Proxy_UA_Middlware类很长。基本上它包含更改代理和用户代理的方法。我在settings.py文件中正确配置了这两个中间件。代理部分工作正常,但用户代理不会更改。我用来更改用户代理的代码如下所示
class CustomRetryMiddleware(RetryMiddleware):
def _retry(self, request, reason, spider):
retries = request.meta.get('retry_times', 0) + 1
if retries <= self.max_retry_times:
Proxy_UA_Middleware.switch_proxy()
Proxy_UA_Middleware.switch_ua()
logger.debug("Retrying %(request)s (failed %(retries)d times): %(reason)s",
{'request': request, 'retries': retries, 'reason': reason},
extra={'spider': spider})
retryreq = request.copy()
retryreq.meta['retry_times'] = retries
retryreq.dont_filter = True
retryreq.priority = request.priority + self.priority_adjust
return retryreq
else:
logger.debug("Gave up retrying %(request)s (failed %(retries)d times): %(reason)s",
{'request': request, 'retries': retries, 'reason': reason},
extra={'spider': spider})
其中self.user_agent是从用户代理数组中获取的随机值。这不起作用。但是,如果我这样做
request.headers.setdefault('User-Agent', self.user_agent)
然后它工作得很好,用户代理每次重试都会成功更改。但我没有看到有人使用此方法来更改用户代理。我的问题是,如果以这种方式更改用户代理是可以的,如果不是,我做错了什么?
答案 0 :(得分:1)
如果您总是希望控制在该中间件上使用哪个用户代理,那么就可以了,setdefault
做的是检查之前是否分配了User-Agent
,这是可能的,因为其他中间件可以这样做,甚至可以从蜘蛛中分配它。
另外我认为你也应该禁用默认的UserAgentMiddleware
,或者甚至为你的中间件设置更高的优先级,检查UserAgentMiddleware
priority is 400,然后将你的设置放在之前(之前的某个数字) 400)。
答案 1 :(得分:0)
首先,您要覆盖前面带有_
(下划线)的函数,该函数在Python中应为“私有”函数。该功能可能会在不同版本的Scrapy中更改,并且您的覆盖将阻碍升级/降级。覆盖它是冒险的。最好在另一个包装_retry
的函数中更改用户代理。
我为此做了一个功能,但是使用了Scrapy伪造的用户代理模块。我找到了两个调用_retry
的函数。因此,重试会在异常和重试状态下发生。重试之前,我们需要在请求中的两个功能上都更改用户代理。这是代码:
from scrapy.downloadermiddlewares.retry import *
from scrapy.spidermiddlewares.httperror import *
from fake_useragent import UserAgent
class Retry500Middleware(RetryMiddleware):
def __init__(self, settings):
super(Retry500Middleware, self).__init__(settings)
fallback = settings.get('FAKEUSERAGENT_FALLBACK', None)
self.ua = UserAgent(fallback=fallback)
self.ua_type = settings.get('RANDOM_UA_TYPE', 'random')
def get_ua(self):
'''Gets random UA based on the type setting (random, firefox…)'''
return getattr(self.ua, self.ua_type)
def process_response(self, request, response, spider):
if request.meta.get('dont_retry', False):
return response
if response.status in self.retry_http_codes:
reason = response_status_message(response.status)
request.headers['User-Agent'] = self.get_ua()
return self._retry(request, reason, spider) or response
return response
def process_exception(self, request, exception, spider):
if isinstance(exception, self.EXCEPTIONS_TO_RETRY) \
and not request.meta.get('dont_retry', False):
request.headers['User-Agent'] = self.get_ua()
return self._retry(request, exception, spider)
不要忘记通过settings.py
启用中间件,并禁用标准重试和用户代理中间件。
DOWNLOADER_MIDDLEWARES = {
'scrapy.downloadermiddlewares.useragent.UserAgentMiddleware': None,
'scrapy.downloadermiddlewares.retry.RetryMiddleware': None,
'my_project.middlewares.Retry500Middleware': 401,
'scrapy_fake_useragent.middleware.RandomUserAgentMiddleware': 400,
}
FAKEUSERAGENT_FALLBACK = "<your favorite user agent>"