Извлечение нескольких URL-адресов с помощью aiohttp в Python 3.5
Начиная с версии Python 3.5 async with
синтаксис, рекомендуемый в документах для aiohttp
изменился Теперь, чтобы получить один URL, они предлагают:
import aiohttp
import asyncio
async def fetch(session, url):
with aiohttp.Timeout(10):
async with session.get(url) as response:
return await response.text()
if __name__ == '__main__':
loop = asyncio.get_event_loop()
with aiohttp.ClientSession(loop=loop) as session:
html = loop.run_until_complete(
fetch(session, 'http://python.org'))
print(html)
Как я могу изменить это, чтобы получить коллекцию URL вместо одного URL?
В старом asyncio
примеры вы бы настроить список задач, таких как
tasks = [
fetch(session, 'http://cnn.com'),
fetch(session, 'http://google.com'),
fetch(session, 'http://twitter.com')
]
Я попытался объединить этот список с подходом, описанным выше, но не получилось.
1 ответ
Решение
Для параллельного выполнения вам нужен asyncio.Task
Я преобразовал ваш пример в одновременную выборку данных из нескольких источников:
import aiohttp
import asyncio
async def fetch(session, url):
async with session.get(url) as response:
if response.status != 200:
response.raise_for_status()
return await response.text()
async def fetch_all(session, urls):
results = await asyncio.gather(*[asyncio.create_task(fetch(session, url))
for url in urls])
return results
async def main():
urls = ['http://cnn.com',
'http://google.com',
'http://twitter.com']
async with aiohttp.ClientSession() as session:
htmls = await fetch_all(session, urls)
print(htmls)
if __name__ == '__main__':
asyncio.run(main())