Python 碎屑/蟒蛇产量和继续加工是否可能?

Python 碎屑/蟒蛇产量和继续加工是否可能?,python,scrapy,return,yield,Python,Scrapy,Return,Yield,我正在尝试这个示例代码 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/

我正在尝试这个示例代码

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
循环之前生成了一个项,那么它只会爬行第一页。(如下图所示)

但是我可以使用
yield Request(url)
而不是
return…
,它会将页面从最后一页向后刮到第一页


我想了解为什么
return
项目产生后不再有效?有人能用一种简单的方式解释一下吗?

因为调用项目/请求应该是生成器函数。 您甚至不能在具有相同“含义”的同一个函数中使用
yield
return
,它将在生成器中使用参数引发
SyntaxError:“return”


返回值
几乎等同于提出StopIteration。在本主题中,您可以找到非常详细的解释和链接规范。

您会问为什么第二个代码不工作,但我认为您不完全理解第一个代码工作的原因:)

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

正在发生的是:

  • self.start\u URL
    中的URL调用
    self.parse()

  • self.parse()

  • 当对第一个URL的响应到达时,
    self.parse()
    再次被调用,这次它从
    self.urls
    返回对第二个URL的请求(仅1个请求!),因为对
    self.parse()
    的上一次调用已经使用了来自它的第一个URL(
    self.urls

  • 最后一步在循环中重复,但不是
    for
    循环完成

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

    def解析(self,response):
    尝试:
    返回下一个(self.url)
    除停止迭代外:
    通过
    
    我不清楚为什么我的问题应该是
    return
    提升
    StopIteration
    ,因为该方法正常工作,除非我使用
    yield
    。因此,如果问题是由于
    StopIteration
    异常引起的,那么第一个示例不应该只抓取第一个url并停止吗?您的解释非常详细,但仍然没有解释
    yield
    停止执行的原因。它不应该返回一个
    返回请求(url)
    ,它将再次返回for循环吗?为什么它会在第一次迭代中停止?据我所知,收益率确实提高了
    StopIteration
    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)