【问题标题】:What response "process_response()" produces when "or response" is returned?返回“或响应”时会产生什么响应“process_response()”?
【发布时间】:2020-10-04 14:05:42
【问题描述】:

我创建了一个使用scrapy 解析网站内容的脚本。脚本运行良好。但是,当蜘蛛中使用的 url 被重定向(导致一些验证码页面)时,我希望该蜘蛛重试,这就是我创建重试中间件的原因。

我试图理解为什么这部分 or responseprocess_response() 这一行 return self._retry(request, reason, spider) or response 中就位,因为我希望这种方法重试,而不是在该块内返回响应。

这是我目前的做法:

def _retry(self, request, spider):
    check_url = request.url
    r = request.copy()
    r.dont_filter = True
    return r

def process_response(self, request, response, spider):
    if ("some_redirected_url" in response.url) and (response.status in RETRY_HTTP_CODES):
        return self._retry(request, spider) or response
    return response

【问题讨论】:

  • 您可以使用request.replace 使用原始URL 创建一个新请求,您可以将其传递给_retry。这就是你要找的吗?
  • 你的问题不是很清楚。看起来你已经从scrapy 中的默认RetryMiddleware 复制了这个(我不确定你想添加什么)。因为有一个最大的重试次数,如果达到,它将只返回response(可能已经失败)。这就是self.retry(...) or response 部分的含义
  • 我的问题可能不太清楚,但您似乎以正确的方式回答了它。我忘记了即使我没有明确定义重试也是有限制的。所以,这部分or response 会在最大退休人数达到其限制时发挥作用,对吧?如果您发布一个,我将很高兴接受您的回答。但是,我已经编辑了我的帖子以使其更清晰。谢谢@tomjn。

标签: python python-3.x web-scraping scrapy


【解决方案1】:

在这种情况下,return x or y 是一个不错的捷径

if x:
    return x
else:
    return y

在标准 RetryMiddleware 中,_retry 方法有两个分支

if retries <= retry_times:
    ...
    return retryreq
else:
    ...    

else 分支不返回任何内容,如果方法到达末尾没有返回,则隐式返回 None。这意味着

return self._retry(request, reason, spider) or response

行计算为

return None or response

由于bool(None)False,在这种情况下将返回response。另一方面,如果没有超过 retry_times_retry 将返回 retryreq,这将评估 True,并将从 process_response 返回。

在您的代码中,_retry 始终返回 Response,因此永远不会到达 or response 部分。

【讨论】:

  • 关于这个的最后一个问题:当_retry 将返回retryreq 将评估True,它怎么会从process_response 返回?更清楚地说,每当执行这行 return True or response 时,都不应到达最后一个 return(位于最底部)。
  • 它被评估为True意味着它被返回。不是return True or response,而是return retryreq or response
【解决方案2】:

@tomjn 已经涵盖了您的中间件问题,但是,作为重试那些 302s 响应的替代方法,您只需告诉 Scrapy 停止重定向 302s 并将它们添加到触发RetryMiddleware。例如:

from scrapy.utils.project import get_project_settings
RETRY_HTTP_CODES = get_project_settings().get("RETRY_HTTP_CODES", [])

class MySpider(CrawlSpider):
    # ...
    # do no redirect on this one
    handle_httpstatus_list = [302]
    # Add "302" to the retry codes list
    custom_settings = {"RETRY_HTTP_CODES": RETRY_HTTP_CODES + [302]}

因此,您不需要为此定制中间件。

【讨论】:

  • 感谢您的替代解决方案@Thiago Curvelo。我知道这一点。问题是,我的问题是为了弄清楚这里应用的逻辑return self._retry(request, reason, spider) or response
猜你喜欢
  • 2010-11-28
  • 2022-01-03
  • 2010-11-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-05-23
  • 2018-10-23
  • 1970-01-01
相关资源
最近更新 更多