Python 使用Scrapy连续抓取域

Python 使用Scrapy连续抓取域,python,scrapy,web-crawler,scrapy-spider,Python,Scrapy,Web Crawler,Scrapy Spider,我在数据库中有要连续爬网的站点,即: 将域添加到允许的域列表(应为空) 将此域添加到请求中(将http://添加到请求中效果很好) 根据允许的域对请求进行爬网 前进到下一个域,仅将其添加到允许的域列表中。它将是那里唯一的一个,因此不会发生交叉。注意:这对我没有帮助,但也许我遗漏了什么 抓取此请求 连续完成我拥有的所有域 到目前为止,我所取得的成就是对域进行爬网,它做得非常好,能够完美地对请求进行爬网。 我唯一的问题是允许的\u域似乎没有更新,它会爬网所有类型的站点 我设置了DEPTH\u LIM

我在数据库中有要连续爬网的站点,即:

  • 将域添加到允许的域列表(应为空)
  • 将此域添加到请求中(将
    http://
    添加到请求中效果很好)
  • 根据允许的域对请求进行爬网
  • 前进到下一个域,仅将其添加到允许的域列表中。它将是那里唯一的一个,因此不会发生交叉。注意:这对我没有帮助,但也许我遗漏了什么
  • 抓取此请求
  • 连续完成我拥有的所有域
  • 到目前为止,我所取得的成就是对域进行爬网,它做得非常好,能够完美地对请求进行爬网。 我唯一的问题是
    允许的\u域
    似乎没有更新,它会爬网所有类型的站点

    我设置了
    DEPTH\u LIMIT=1
    ,这样它就不会是无限爬网,我还添加了DF爬网而不是BF爬网:

    DEPTH_LIMIT= 1
    SCHEDULER_DISK_QUEUE = 'scrapy.squeues.PickleFifoDiskQueue'
    SCHEDULER_MEMORY_QUEUE = 'scrapy.squeues.FifoMemoryQueue'
    
    以下是我的spider的代码(只是开始;因为您并不真正关心我的项目处理…):

    extract\u raw\u recipe
    的代码没有请求或解析下一个url,它只是工作,所以不需要编辑它。但是如果我需要添加一些内容,请告诉我,因为这可能是缺少的链接。当前代码向项添加一个字典,然后将该项放入数据库中

    总之:我需要添加什么,使它在每次爬网请求时过滤域


    如果需要提供更多的代码,请告诉我。

    我的建议是采取完全不同的方法。在需要爬网的域数据库中创建一个队列(基于您想要的任何标准),然后选择一个域进行爬网,并使用
    允许的\u域列表中的相关域初始化爬行器。爬行器完成后,重新开始下一个域的另一次爬网。重复此操作,直到队列中的所有域都完成

    这将为您提供对整个过程的更多控制(例如,重新排队失败的爬网、取消有问题的爬网并在不丢失进度的情况下继续前进、一次爬网多个域而无“串扰”等)。如果您计划扩展此功能,它还将允许您执行自定义设置等操作(例如,用户代理、DUPEFILTER、下载延迟)或基于每个域的自定义规则,显著扩展了爬行器的可用性


    如果这不是一个选项,你可以重置你的
    允许的\u域列表。这样做有一些问题,但首先要了解一下Scrapy的异地过滤的背景

    OffSiteMiddleware
    负责根据
    allowed_domains
    编译允许域的列表。它为此使用了一个正则表达式,在spider启动时只编译一次(使用
    spider_opened
    信号)。更新变量
    allowed_domains
    将不会对爬行器产生影响,除非您还强制
    offsedimiddleware
    重新编译其正则表达式

    以下方法(放置在spider中)应可用于用新列表替换
    允许的\u域

    from scrapy.spidermiddlewares.offsite import OffsiteMiddleware
    
    def change_allowed_domains(self, allowed_domains):
        self.allowed_domains = allowed_domains
    
        for middleware in self.crawler.engine.scraper.spidermw.middlewares:
            if isinstance(middleware, OffsiteMiddleware):
                middleware.spider_opened(self)
    
    这将重置
    OffsiteMiddleware
    所使用的
    集()
    ,因此,如果您将其用于其他用途,请记住这一点

    因此,花一秒钟的时间来消化所有这些,一个问题开始浮出水面:当您在
    start\u请求()
    中对每个域排队时,您当前更改
    允许的\u域的方法将不起作用,因为
    Spider
    类只跟踪一个
    允许的\u域
    正则表达式(与请求/响应对象完全不关联)。如果在爬行器开始爬网之前将20个请求排队到不同的域(每次更改
    允许的\u域
    列表),它将使用最新编译的正则表达式(即最后排队的域的
    允许的\u域

    要克服这一点,您需要对一个域的所有请求进行爬网,编写自己的
    OffsiteMiddleware
    ,并让它处理所有筛选。或者您可以创建一个不同的域,以便在队列中的所有请求完成且下载程序中的所有插槽都为空时,将下一个域添加到列表中(可能是通过检查self.crawler.engine.slot.inprogress
    和'self.crawler.engine.slot.scheduler')


    祝你好运!

    对不起,现在只有时间和资源来阅读你的答案。哇,它给了我很多思考和考虑,非常感谢,会尝试和更新。尝试它,它很好地分离请求,并让刮处理每个网站作为一个单独的线程。
    from scrapy.spidermiddlewares.offsite import OffsiteMiddleware
    
    def change_allowed_domains(self, allowed_domains):
        self.allowed_domains = allowed_domains
    
        for middleware in self.crawler.engine.scraper.spidermw.middlewares:
            if isinstance(middleware, OffsiteMiddleware):
                middleware.spider_opened(self)