scrapy:由信号调用的回调的yield请求



我有一个spider,它可以抓取一些数据并向管道生成一个项。然后,管道检查数据库中是否存在此数据。如果没有,它会丢弃项目。spider是信号连接的,用于调用item_drop信号的回调。我想从item_dropped回调中向不同的url发出另一个请求,以用额外的数据填充同一个项目。如果我没有在回调中包含yield语句,它就会触发,但如果我包含了,它就不会,我不知道为什么。

(为简洁起见,已简化(

MySpider.py:

def from_crawler(cls, crawler, *args, **kwargs):
spider = super(MySpider, cls).from_crawler(crawler, *args, **kwargs)
crawler.signals.connect(spider.item_dropped, signal=signals.item_dropped)
return spider
[ ...parse start url and yield to pipeline here... ]
def item_dropped(self, item, response, exception, spider,):
print("ITEM ERROR CAUGHT")
yield Request(
url="http://www.example.com/api/data",
callback=self.parse_request_2,
cb_kwargs=dict(item=item))

MyPipeline.py:

def process_item(self, item, spider):
/* ORM model mapping */
data = Data(
name = item['name']
)
data_exists = self.session.query(exists().where(Data.name == item['name'])).scalar()

if data_exists is False:
raise DropItem("DATA_INCOMPLETE")

我尝试这样做的原因是,新对象不断添加到第一个url中,所以我需要反复抓取它,但它并没有包含我需要的所有数据。然后,我需要抓取一个不同的url,以便将其他数据添加到该项目中,但只有一次,即该项目第一次添加到数据库时。

如何从item_dropped回调中获取另一个请求?更重要的是,我这样做是正确的,还是有更好的方法来实现这一点?我知道我可以在spider中进行数据库检查,并在那里实现回调逻辑,但我不希望spider和管道都打开数据库会话。

您不能从该信号中产生请求。

您必须将代码移动到spider中间件中,或者将其移动到spider中的请求回调中。

最新更新