Корутины

Добавлено в версии 2.0.

У Scrapy есть частичная поддержка вместо синтаксис корутины.

Поддерживаемые вызываемые объекты

Следующие вызываемые объекты могут быть определены как корутины с использованием async def и, следовательно, использовать синтаксис корутин (например, await, async for, async with):

Использование

В Scrapy есть несколько вариантов использования корутин. Код, который возвращал Отложенные при написании для предыдущих версий Scrapy, таких как промежуточное программное обеспечение загрузчика и обработчики сигналов, можно переписать, сделав его короче и чище:

from itemadapter import ItemAdapter

class DbPipeline:
    def _update_item(self, data, item):
        adapter = ItemAdapter(item)
        adapter['field'] = data
        return item

    def process_item(self, item, spider):
        adapter = ItemAdapter(item)
        dfd = db.get_some_data(adapter['id'])
        dfd.addCallback(self._update_item, item)
        return dfd

становится:

from itemadapter import ItemAdapter

class DbPipeline:
    async def process_item(self, item, spider):
        adapter = ItemAdapter(item)
        adapter['field'] = await db.get_some_data(adapter['id'])
        return item

Корутины могут использоваться для вызова асинхронного кода. Сюда входят другие корутины, функции, возвращающие Отложенные, и функции, возвращающие ожидаемыми объектами, например Future. Это означает, что вы можете использовать множество полезных библиотек Python, предоставляющих такой код:

class MySpiderDeferred(Spider):
    # ...
    async def parse(self, response):
        additional_response = await treq.get('https://additional.url')
        additional_data = await treq.content(additional_response)
        # ... use response and additional_data to yield items and requests

class MySpiderAsyncio(Spider):
    # ...
    async def parse(self, response):
        async with aiohttp.ClientSession() as session:
            async with session.get('https://additional.url') as additional_response:
                additional_data = await additional_response.text()
        # ... use response and additional_data to yield items and requests

Примечание

Многие библиотеки, использующие сопрограммы, такие как aio-libs, требуют цикла asyncio, а для их использования необходим активированная asyncio поддержка в Scrapy.

Примечание

Если вы хотите использовать await на Отложенных при использовании реактора asyncio, вам нужно завернуть их.

Общие варианты использования асинхронного кода включают:

  • запрос данных с веб-сайтов, баз данных и других служб (в обратных вызовах, конвейерах и промежуточном программном обеспечении);

  • хранение данных в базах данных (в конвейерах и промежуточном ПО);

  • задержка инициализации паука до некоторого внешнего события (в обработчике spider_opened);

  • вызов асинхронных методов Scrapy, таких как ExecutionEngine.download (см. пример конвейера скриншотов).