【问题标题】:Scrapy - Correct way to change User Agent in RequestScrapy - 在请求中更改用户代理的正确方法
【发布时间】:2015-12-21 16:32:40
【问题描述】:

我通过覆盖 RetryMiddleware 在 Scrapy 中创建了一个自定义中间件,该中间件在重试之前会同时更改代理和用户代理。看起来是这样的

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})

Proxy_UA_Middlware 类很长。基本上它包含更改代理和用户代理的方法。我在我的 settings.py 文件中正确配置了这两个中间件。代理部分工作正常,但用户代理没有改变。我用来改变用户代理的代码是这样的

request.headers.setdefault('User-Agent', self.user_agent)

其中 self.user_agent 是从用户代理数组中获取的随机值。这行不通。但是,如果我这样做

request.headers['User-Agent'] = self.user_agent

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

【问题讨论】:

    标签: python scrapy screen-scraping user-agent


    【解决方案1】:

    如果你总是想控制在那个中间件上使用哪个用户代理,那没关系,setdefault 所做的就是检查之前是否没有分配User-Agent,这是可能的,因为其他中间件可能是这样做,甚至从蜘蛛分配它。

    另外我认为你还应该禁用默认的UserAgentMiddleware,甚至为你的中间件设置更高的优先级,检查UserAgentMiddleware priority is 400,所以将你的设置为之前(400之前的某个数字)。

    【讨论】:

      【解决方案2】:

      首先,您要覆盖前面带有_(下划线)的函数,它应该是Python 中的“私有”函数。该功能可能会在不同版本的 Scrapy 中发生变化,您的覆盖将阻碍升级/降级。覆盖它对你来说是有风险的。最好在另一个包装_retry的函数中更改用户代理。

      我已经为此创建了一个函数,但使用了 Scrapy fake 用户代理模块。我发现有两个函数调用_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>"
      

      【讨论】:

      猜你喜欢
      • 2018-02-12
      • 1970-01-01
      • 2020-09-26
      • 2010-11-16
      • 2020-08-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多