将链,组和块与芹菜结合在一起

时间:2017-07-13 13:51:59

标签: python celery

我想将Celery用作Url抓取器。

我有一个Url列表,我必须对每个URL执行HTTP请求,并将结果写入文件(整个列表的文件相同)。

我的第一个想法是在Celery调用的任务中使这个代码击败每个 n 分钟:

@app.task
def get_urls(self):
    results = [get_url_content.si(
        url=url
    ) for url in urls]

    ch = chain(
        group(*results),
        write_result_on_disk.s()
    )

    return ch()

此代码运行良好,但有一个问题:我有一千个要抓取的URL,如果其中一个get_url_content失败,则不会调用write_result_on_disk,我们会丢失之前抓取的所有内容。

我想要做的是通过拆分URL来获取 chunk 任务,获取结果并将其写入磁盘。例如,20个URL的内容写在磁盘上。

请问您有什么想法吗?我尝试了chunks()函数,但没有得到真正有用的结果。

1 个答案:

答案 0 :(得分:2)

使用CeleryBeat进行类似cron的任务是一个好主意。

我会尝试在get_url_content微任务中捕获异常。当你抓住它们时,只需返回别的东西。这样,您可以在summarize_task中评估(例如计数,列表,检查)。

如何将链用于其他任务:

第1步:将块转换为组:

http://docs.celeryproject.org/en/latest/userguide/canvas.html#chunks中所述,.group()将类型celery.canvas.chunks的对象转换为一个组,这是Celery中更常见的类型。

第2步:将群组和任务联系起来

http://docs.celeryproject.org/en/latest/userguide/canvas.html#the-primitives提到的“通过合并打击你的想法”一节:

  

将一个组与另一个任务链接在一起会自动升级   它是一个和弦

以下是一些代码,包含两个任务以及我通常如何调用它们:

@app.task
def solve_micro_task(arg: str) -> dict:
    ...

@app.task
def summarize(items: List[List[dict]]):
    flat_list = [item for sublist in items for item in sublist]
    for report in flat_list:
        ...

chunk_tasks = solve_micro_task.chunks(<your iterator, e.g., a list>), 10)  # type: celery.canvas.chunks
summarize_task = summarize.s()
chain(chunk_tasks.group(), summarize_task)()