【问题标题】:Scrapy start_requests() didn't yield all requestsScrapy start_requests() 没有产生所有请求
【发布时间】:2021-02-19 10:49:29
【问题描述】:
    def start_requests(self):
        db = SeedUserGenerator()
        result = db.selectSeedUsers()
        db.closeDB()
        urls = []
        for name in result:
            urls.append(self.user_info_url.format(name))
        for url in urls:
            yield Request(url=url, callback=self.parse_user, dont_filter=False, priority=10)
        print('fin')

    def parse_user(self, response):
        .........ignore some code here...........
        yield Request(url=next_url, priority=20, callback=self.parse_info)

    def parse_info(self, response):
        .........ignore some code here...........
        yield Request(url=next_url, priority=30, callback=self.parse_user)

程序运行如下:

  1. 来自start_requests 的多个请求产生,并且函数start_requests 似乎在没有输出字符串fin 的情况下暂停。
  2. 一个响应来了,函数parse_useryield了另一个Request,但是函数start_requests中剩下的Requests直到响应处理完才能yield,这里yield操作形成了一个环。

好像是 同步:在从start_requests发送一个Request并处理它的响应之前,其他Request不能yield?

这是否意味着scrapy 永远无法在函数start_requests 中产生剩余的请求?

我怎样才能让scrapy先跑完start_requests

我是 python 和 scrapy 的新手。 scrapy 可以同时处理响应和产生请求吗?

顺便说一下,我用的是 Python3.6 和 Scrapy1.5.1 Twisted 20.3.0

【问题讨论】:

    标签: scrapy


    【解决方案1】:

    我参考了Scrapy引擎的源码解决了我的问题:

        def _next_request(self, spider):
            slot = self.slot
            if not slot:
                return
    
            if self.paused:
                return
    
            while not self._needs_backout(spider):
                if not self._next_request_from_scheduler(spider):
                    break
    
            if slot.start_requests and not self._needs_backout(spider):
                try:
                    request = next(slot.start_requests)
                except StopIteration:
                    slot.start_requests = None
                except Exception:
                    slot.start_requests = None
                    logger.error('Error while obtaining start requests',
                                 exc_info=True, extra={'spider': spider})
                else:
                    self.crawl(request, spider)
    
            if self.spider_is_idle(spider) and slot.close_if_idle:
                self._spider_idle(spider)
    

    这里 Scrapy 总是首先尝试从调度程序的队列中获取请求,而不是 start_requests。

    更重要的是,Scrapy 从来没有把函数 start_requests 的所有请求放在第一位。

    所以,我像这样更改我的代码:

        def start_requests(self):
            db = SeedUserGenerator()
            result = db.selectSeedUsers()
            db.closeDB()
            urls = []
            for name in result:
                urls.append(self.user_info_url.format(name))
            yield Request(url=urls[0], callback=self.parse_temp, dont_filter=True, priority=10, meta={'urls': urls})
    
        def parse_temp(self, response):
            urls = response.meta['urls']
            for url in urls:
                print(url)
                yield Request(url=url, callback=self.parse_user, dont_filter=False, priority=10)
            print('fin2')
    

    然后 Scrapy 将所有请求先放入队列中。

    【讨论】:

      猜你喜欢
      • 2017-08-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-07-26
      相关资源
      最近更新 更多