我正在尝试此示例代码
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
后不再起作用?有人可以用简单的方式解释吗?
答案 0 :(得分:1)
您问为什么第二个代码不起作用,但是我认为您不完全理解第一个代码为什么起作用:)
第一个代码的for
循环仅循环一次。
正在发生的事情是:
self.parse()
中的URL调用 self.start_urls
。
self.parse()
从self.urls
获取第一个(也是第一个!)URL,然后将其返回,退出self.parse()
。
当第一个URL的响应到达时,self.parse()
再次被调用,这一次它从self.urls
返回对第二个URL的请求(仅一个请求!),因为先前对self.parse()
的调用已经消耗了它的第一个URL(self.urls
是iterator)。
最后一步在一个循环中重复,但不是for
循环执行。
您可以将原始代码更改为此,并且将以相同的方式工作:
def parse(self, response):
try:
return next(self.urls)
except StopIteration:
pass
答案 1 :(得分:0)
由于要调用项目/请求,因此应为 generator 函数。
您甚至不能在具有相同“含义”的同一函数中使用MyApp::Application.config.session_store :cookie_store, domain: 'something.rootdomain.com'
和yield
,它将引发return
。
SyntaxError: 'return' with argument inside generator
(几乎)等同于提高StopIteration。在本主题Return and yield in the same function中,您可以找到非常详细的说明以及链接说明。