首页 > 解决方案 > 除非中间有 200 个状态,否则无法强制脚本重试五次

问题描述

我使用scrapy创建了一个脚本,它能够递归地重试列表中的一些链接,即使这些链接无效并得到404响应。我使用dont_filter=Trueand 'handle_httpstatus_list': [404]insidemeta来实现当前的行为。我现在要做的是让脚本做同样的事情 5 次,除非200 status中间有。我已经考虑"max_retry_times":5meta这样一个事实,即它最多会重试五次,但它只是无限重试。

到目前为止我已经尝试过:

import scrapy
from bs4 import BeautifulSoup
from scrapy.crawler import CrawlerProcess

class StackoverflowSpider(scrapy.Spider):
    name = "stackoverflow"
    start_urls = [
        "https://stackoverflow.com/questions/taggedweb-scraping",
        "https://stackoverflow.com/questions/taggedweb-scraping"
    ]

    def start_requests(self):
        for start_url in self.start_urls:
            yield scrapy.Request(start_url,callback=self.parse,meta={"start_url":start_url,'handle_httpstatus_list': [404],"max_retry_times":5},dont_filter=True)

    def parse(self,response):
        if response.meta.get("start_url"):
            start_url = response.meta.get("start_url")

        soup = BeautifulSoup(response.text,'lxml')
        if soup.select(".summary .question-hyperlink"):
            for item in soup.select(".summary .question-hyperlink"):
                title_link = response.urljoin(item.get("href"))
                print(title_link)

        else:
            print("++++++++++"*20) # to be sure about the recursion
            yield scrapy.Request(start_url,meta={"start_url":start_url,'handle_httpstatus_list': [404],"max_retry_times":5},dont_filter=True,callback=self.parse)
            
if __name__ == "__main__":
    c = CrawlerProcess({
        'USER_AGENT':'Mozilla/5.0',
    })
    c.crawl(StackoverflowSpider)
    c.start()

如何让脚本最多重试五次?

注意:列表中有多个相同的 url。我不想踢出重复的链接。我想让scrapy使用所有的网址。

标签: pythonpython-3.xweb-scrapingscrapy

解决方案


我可以建议以下方向:
1. 将404代码添加到RETRY_HTTP_CODES设置中,因为它默认不包含响应代码404

即使链接无效并获得 404 响应,也能够递归重试链接

class StackoverflowSpider(scrapy.Spider):
    name = "stackoverflow"
    custom_settings = {
        'RETRY_HTTP_CODES' : [500, 502, 503, 504, 522, 524, 408, 429 , 404],
        'RETRY_TIMES': 5 # usage of "max_retry_times" meta key is also valid
    }
....
  1. with dont_filter=True- scrapy 应用程序将访问以前访问过的页面。
    从您的代码中删除 dont_filter=True应该可以解决无限循环问题

但它只是无限重试。


推荐阅读