【问题标题】:scrapy: yield request from callback called by signalscrapy:从信号调用的回调中产生请求
【发布时间】:2020-04-24 03:51:16
【问题描述】:

我有一个爬虫,它会抓取一些数据并为管道生成一个项目。然后管道检查数据库中是否存在此数据。如果没有,它会丢弃该项目。蜘蛛是信号连接的,以调用 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 以将其他数据添加到该项目,但只有一次,即第一次将该项目添加到数据库中。

如何让 scrapy 从 item_dropped 回调中产生另一个请求?更重要的是,我是否以正确的方式进行此操作,还是有更好的方法来完成此操作?我知道我可以从蜘蛛内部进行数据库检查并在那里实现回调逻辑,但我宁愿不要让蜘蛛和管道都打开数据库会话。

【问题讨论】:

    标签: python sqlalchemy scrapy


    【解决方案1】:

    您无法从该信号中产生请求。

    您必须将您的代码移动到 spider middleware 或将其移动到您的蜘蛛中的请求回调中。

    【讨论】:

    • 我相信他可以检查是否发出信号然后进行相应处理
    • 您不能从信号中产生请求。最多你可以走一个 hacky 的方式并调用 spider.crawler.engine.crawl 或其他东西,但蜘蛛中间件可能是更好的选择。
    猜你喜欢
    • 2017-08-30
    • 2016-11-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-02-25
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多