【问题标题】:Scrapy and celery `update_state`Scrapy 和 celery `update_state`
【发布时间】:2017-06-12 11:48:25
【问题描述】:

我有以下设置(Docker):

  • Celery 链接到运行 Scrapy 蜘蛛的 Flask 设置
  • 烧瓶设置(显然)
  • Flask setup 收到对 Scrapy 的请求 -> 启动 worker 来做一些工作

现在我想根据芹菜工人的进度更新原始烧瓶设置。 但是目前无法在刮刀内部使用celery.update_state(),因为它无法访问原始任务(尽管它正在 celery 任务内部运行)。

顺便说一句:我是否遗漏了有关 scrapy 结构的一些内容?我可以在__init__ 中分配参数以便能够进一步使用,这似乎是合理的,但scrapy 似乎将该方法用作lambda 函数..


回答一些问题:

  • How are you using celery with scrapy? Scrapy 在 celery 任务中运行,而不是从命令行运行。我也没有听说过scrapyd,这是scrapy的子项目吗?我使用远程工作人员从 celery/flask 实例内部触发 scrapy,因此它与原始请求所实例化的线程不同,它们是单独的 docker 实例。

task.update_state 效果很好!在 celery 任务中,但是一旦我们“进入”蜘蛛,我们就不再可以访问 celery。有什么想法吗?

来自 item_scraped 信号问题 Task.update_state(taskid,meta={})。如果scrapy恰好在Celery任务本身中运行(因为它默认为self),您也可以在没有taskid的情况下运行

这有点像访问当前 celery 任务的静态方式吗?因为我会喜欢那个....

【问题讨论】:

    标签: python scrapy celery scrapy-pipeline


    【解决方案1】:

    我不确定你是如何发射蜘蛛的,但我遇到了你描述的同样的问题。

    我的设置是烧瓶作为休息 api,它会根据请求触发 celery 任务以启动蜘蛛。我还没有编写代码,但我会告诉你我在想什么:

    from scrapy.settings import Settings
    from scrapy.utils.project import get_project_settings
    from twisted.internet import reactor
    from scrapy.crawler import CrawlerRunner
    from scrapy.utils.log import configure_logging
    from scrapy import signals
    from .your_celery import app
    
    
    
    @app.task(bind=True)
    def scrapping(self):
    
        def my_item_scrapped_handler(item, response, spider):
            meta = {
                # fill your state meta as required based on scrapped item, spider, or response object passed as parameters
            }
    
            # here self refers to the task, so you can call update_state when using bind
            self.update_state(state='PROGRESS',meta=meta)
    
        settings = get_project_settings()
        configure_logging({'LOG_FORMAT': '%(levelname)s: %(message)s'})
    
        runner = CrawlerRunner(settings)
        d = runner.crawl(MySpider)
        d.addBoth(lambda _: reactor.stop())
    
        for crawler in runner.crawlers:
            crawler.signals.connect(my_item_scrapped_handler, signal=signals.item_scraped)
    
    
        reactor.run()
    

    很抱歉无法确认它是否有效,但一旦我开始测试它,我会在这里报告!我目前无法为这个项目投入尽可能多的时间:(

    如果您认为我可以进一步帮助您,请随时与我联系!

    干杯,拉米罗

    来源:

    【讨论】:

    • 哇,伙计,我确实解决了它。但感谢您的意见!最后我用和你一样的方式处理它,尽管涉及的少了一点
    【解决方案2】:

    需要更多信息来回答这个问题。

    你如何在 Scrapy 中使用 celery? scrapy 是否在 celery 任务中运行? 如果它对您的项目有意义scrapyd,我强烈建议在它自己的服务器下运行scrapy。

    如果不是,那么 item_scraped 信号会很好,但前提是您可以访问 Celery taskid 或 Celery 任务对象本身。 http://docs.celeryproject.org/en/latest/reference/celery.app.task.html

    来自 item_scraped 信号问题Task.update_state(taskid,meta={})。如果 scrapy 恰好在 Celery 任务本身中运行,您也可以不使用 taskid 运行(因为它默认为 self

    【讨论】:

    • 更新了我的问题,希望我澄清了一些事情。 @RabidCicada
    猜你喜欢
    • 2017-03-08
    • 2013-12-29
    • 2014-04-02
    • 2016-04-10
    • 1970-01-01
    • 2015-10-08
    • 1970-01-01
    • 2017-12-21
    相关资源
    最近更新 更多