Корутины
Добавлено в версии 2.0.
У Scrapy есть частичная поддержка вместо синтаксис корутины.
Поддерживаемые вызываемые объекты
Следующие вызываемые объекты могут быть определены как корутины с использованием async def
и, следовательно, использовать синтаксис корутин (например, await
, async for
, async with
):
Request
обратные вызовы.Примечание
Вывод обратного вызова не обрабатывается, пока не завершится весь обратный вызов.
В качестве побочного эффекта, если обратный вызов вызывает исключение, ни один из его выходных данных не обрабатывается.
Это известная оговорка текущей реализации, которую мы стремимся устранить в будущей версии Scrapy.
Метод
process_item()
из конвейеров элементов.Методы
process_request()
,process_response()
иprocess_exception()
из промежуточного программного обеспечения загрузчика.
Использование
В 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
(см. пример конвейера скриншотов).