在Scrapy文档中,这段代码用于说明如何将信息传递给回调函数。我的问题是,这段代码所在的CrawlSpider
类如何知道执行生成的请求对象?这是简单的编码行为吗?此外,是否使用yield
而不是return
来保持函数运行,并准备好在抓取多个url时接受更多的Response
对象?如果只抓取1个url,返回Request
对象是否同样有效?如果这些是基本问题,我道歉,我以前没有使用过Python或Scrapy。
def parse(self, response):
request = scrapy.Request('http://www.example.com/index.html',
callback=self.parse_page2,
cb_kwargs=dict(main_url=response.url))
request.cb_kwargs['foo'] = 'bar' # add more arguments for the callback
yield request
def parse_page2(self, response, main_url, foo):
yield dict(
main_url=main_url,
other_url=response.url,
foo=foo,
)
3条答案
按热度按时间uujelgoq1#
Scrapy框架有意地抽象了大量的复杂性,使编码爬虫对用户来说看起来微不足道。因此,有许多特性看起来像是“魔术”。在您的示例中,
CrawlSpider
知道执行产生的请求,因为调用您的自定义解析方法的方法被编程为期望同样多的请求。您可能还注意到,您实际上从未调用过任何解析方法它们由scrapy内部引擎调用,因此当您返回parse方法的结果时,这些结果将被传递回调用者并在内部进行处理。一旦接收到它,它将通过各种过程来检查返回的对象是否是Item
类对象,如果是,它将把它传递给其他中间件和Item管道。或者另一个Request
对象,在这种情况下,它会将该对象添加到尚未处理的内部Scheduler
请求队列中。这可能看起来很不寻常,特别是如果您只习惯于处理那些由开发人员负责将所有东西拼凑在一起的库,但在较大的框架中,这并不一定罕见。yield
语句提供了一种更灵活的迭代方式,并创建了generator
对象。它允许您一次生成一个结果,并将其传递给其他进程,而不必一次计算所有可迭代对象;之后,它可能会也可能不会跳回并移动到下一个项目。在许多情况下,yield
输入一个单一的项目与返回它的作用是一样的。但也有一些例外,例如,如果在yield语句之后有任何剩余的清理代码。因此,当使用框架和API(如scrapy)时,我建议您坚持使用文档中推荐的任何内容。4nkexdtk2#
Yield -“yield语句挂起函数的执行并将一个值发送回调用者,但保留足够的状态以使函数能够从它停止的地方继续执行。当继续执行时,函数在最后一次yield运行后立即继续执行。这允许其代码随着时间的推移产生一系列值,而不是立即计算它们并像列表一样将它们发送回。”
因此,这基本上将yield传递给了前面提到的
CrawlSpider
类dgtucam13#
我想你问的是Scrapy引擎,你可以从这里了解更多关于体系结构的信息Architecture overview。
关于你的问题,关于引擎如何区别于请求对象或条目或简单的字典,我相信引擎会检查产生的每个对象,如果它是请求对象或字典,等等。
它怎么能这样做呢?
只需使用
isinstance
-〉isinstance(object, type)
因此,假设正在生成请求,引擎将执行以下操作
因此只需检查生成的对象的类型,引擎就可以决定要执行的操作。