Scrapy - 在请求中更改用户代理的正确方法

时间:2015-12-21 16:32:41

标签: python scrapy screen-scraping user-agent

我通过覆盖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)

然后它工作得很好,用户代理每次重试都会成功更改。但我没有看到有人使用此方法来更改用户代理。我的问题是,如果以这种方式更改用户代理是可以的,如果不是,我做错了什么?

2 个答案:

答案 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>"