Scrapy / Python产量和继续处理可能吗?

问题描述 投票:0回答:2

我正在尝试这个示例代码

from scrapy.spiders import Spider, Request  
import scrapy

class MySpider(Spider):

    name = 'toscrapecom'
    start_urls = ['http://books.toscrape.com/catalogue/page-1.html']

    urls = (
        'http://books.toscrape.com/catalogue/page-{}.html'.format(i + 1) for i in range(50)
    )

    def parse(self, response):
        for url in self.urls:
            return Request(url)

它可以很好地抓取所有页面。但是,如果我在for循环之前生成一个项目,那么它只会抓取第一页。 (如下所示)

from scrapy.spiders import Spider, Request  
import scrapy

class MySpider(Spider):

    name = 'toscrapecom'
    start_urls = ['http://books.toscrape.com/catalogue/page-1.html']

    urls = (
        'http://books.toscrape.com/catalogue/page-{}.html'.format(i + 1) for i in range(50)
    )

    def parse(self, response):
        yield scrapy.item.Item()
        for url in self.urls:
            return Request(url)

但我可以使用yield Request(url)而不是return...,它会从最后一页到第一页向后翻页。

我想了解为什么return一旦产生item就不再起作用了?有人可以用一种简单的方式解释这个吗?

python scrapy return yield
2个回答
1
投票

你问为什么第二个代码不起作用,但我不认为你完全理解为什么第一个代码工作:)

第一个代码的for循环只循环一次。

发生的事情是:

  1. self.parse()中调用self.start_urls的URL。
  2. self.parse()self.urls获取第一个(也是第一个!)URL,并返回它,退出self.parse()
  3. 当第一个URL的响应到来时,self.parse()再次被调用,这次它从self.urls返回第二个URL的请求(只有1个请求!),因为之前对self.parse()的调用已经消耗了它的第一个URL(self.urls是一个iterator)。

最后一步在循环中重复,但它不是for循环。

您可以将原始代码更改为此代码,它将以相同的方式工作:

def parse(self, response):
    try:
        return next(self.urls)
    except StopIteration:
        pass

0
投票

因为要调用项目/请求它应该是生成器函数。你甚至不能在具有相同“意义”的相同功能中使用yieldreturn,它会提升SyntaxError: 'return' with argument inside generator

return(几乎)相当于提高StopIteration。在这个主题Return and yield in the same function你可以找到非常详细的解释,链接规范。

© www.soinside.com 2019 - 2024. All rights reserved.