请问yield item时能不能指定某条管道
来源:4-19 pipeline数据库保存
Edwardsr
2022-07-19
每次yield item都会遍历所有管道么?
比如在parse里想从数据库中查询一下某个id是否存在,根据结果进行下一步,而这时item里的值不适合其他管道。
再比如商品封面图片,商品详情图片需要存入不同的数据库字段,这两者应当用不同的管道来下载,有时只需要下载封面不需要详情图片。
我目前能想到的办法是用item['msg']来记录自己准备干嘛,
item['msg']='check_cover_exist'
yield item
if item['msg'] =='cover_exist':
#经数据库查询封面文件md5值已存在,不爬取详情页
else:
#封面不存在,爬取详情页
在管道里加入下面的代码来判断该管道的职责
if item['msg'] != 'check_cover_exist':
return item
...
#经检查封面存在后
item['msg']='cover_exist'
return item
但我不知该加在哪个方法里,特别是对于下载图片的管道。
----------
经过调式我发现这种情况似乎只能用同步代码,不能用yield,上面的if item['msg'] =='cover_exist':无法得到预期的结果,因为我发现图片管道ImagesPipeline接收到item只是生成了get_media_requests()请求,并没有立刻去发送请求,直到item_completed()才能去判断上文中的封面文件md5是否已在数据库中存在,而这时的代码连详情页都已经爬过了。
1回答
-
bobby
2022-07-21
scrapy的pipeline是作用于所有的item, 如果你想要不同的item有不同的处理逻辑,每个pipeline你写一个函数专门校验一下这个item是否是你感兴趣的item就行了,比如你可以每次yield一个item的时候设置一个type字段表明这是一个什么item,然后你写每个pipeline的时候都去检查一下这个item你是否感兴趣,不敢兴趣就直接return给下一个pipeline处理就可以了啊,如果感兴趣你就按照你的逻辑处理就行了,但是记得这个处理完成以后要继续return防止你后面还有其他的pipeline感兴趣,你要是不喜欢这种方式,直接在你parse函数中解析完成以后直接入库也可以啊, 不过建议自己写pipeline处理,不要把解析和入库等逻辑放在一起, 更有甚者,也是更推荐的方式就是你只写一个pipeline,这个pipeline只做一件事,就是把这条数据放入kafka队列,不同的item类型入到不同的topic下面,然后再单独启动一个消费者消费不同的topic即可,当然这里如果对kafka不熟悉使用redis的订阅功能也是一样的
00
相似问题