Scrapy执行机制疑问:yield、生成器及parse循环执行逻辑解析
聊聊Scrapy里的yield和生成器逻辑
嘿,我完全懂这种困惑——Scrapy把生成器用得出神入化,刚接触的时候确实容易把脑子绕晕。咱们一个个来解决你的问题:
1)Scrapy里yield的工作原理
首先得把Scrapy的爬虫引擎和生成器特性结合起来看:
- 普通Python生成器里,
yield是用来暂停函数执行、返回值,下次调用next()时再从暂停处继续。 - 在Scrapy里,
parse(或其他回调函数)本质是生成器函数,它yield的不是普通值,而是Request对象或Item对象。 - Scrapy引擎会自动迭代这个生成器:每次你
yield一个对象,引擎就会接住它——如果是Request,就丢给调度器排队,等调度器安排后发送请求,拿到响应再调用Request指定的回调(比如你说的parse_author);如果是Item,就传给数据管道处理。 - 关键是,
yield之后parse会暂停执行,等引擎处理完当前这个yield的对象,再回到parse暂停的位置,继续往下走。
2)为什么parse_author会在两个循环执行完后才被调用?
你观察到的现象,核心是Scrapy的调度逻辑:
- 当你在第一个循环里
yield Request(..., callback=parse_author)时,Scrapy并不会立刻调用parse_author,而是把这个Request放到调度队列里排队。 - 这时候
parse不会停下来等parse_author执行,而是继续往下走——先把第一个循环的所有元素遍历完,yield完所有作者页面的Request,再执行第二个循环处理逻辑(比如yield Item)。 - 只有当
parse的生成器把所有代码执行完(或者说引擎把parse生成器里的所有yield都取完),调度器才会从队列里取出那些Request,依次发送请求,拿到响应后才会调用对应的parse_author。 - 简单说:
parse先把所有要产出的Request和Item都“交”给引擎,引擎先排好任务队列,再逐个执行请求、调用回调。所以你会看到parse里的循环先跑完,parse_author才开始工作。
举个直观例子:假设第一个循环有2个作者链接,第二个循环有1个Item,那parse会先产出2个Request,再产出1个Item——这三个对象先被引擎收下,之后调度器才处理那2个Request,触发parse_author的调用。
内容的提问来源于stack exchange,提问作者ulab
相关产品推荐
相关产品推荐

