Python: Pyppeteer с asyncio
Я делал некоторые тесты, и мне интересно, если скрипт ниже работает асинхронно?
# python test.py It took 1.3439464569091797 seconds.
31 (сайтов) х 1,34 = 41,54 с - так что это на несколько секунд меньше, но теоретически это займет всего столько времени, сколько самый длинный запрос?
# python test.py It took 28.129364728927612 seconds.
Возможно, открытие браузера здесь не является асинхронным, и я должен использовать executor для этого?
# cat test.py
import asyncio
import time
from pyppeteer import launch
from urllib.parse import urlparse
WEBSITE_LIST = [
'http://envato.com',
'http://amazon.co.uk',
'http://amazon.com',
'http://facebook.com',
'http://google.com',
'http://google.fr',
'http://google.es',
'http://google.co.uk',
'http://internet.org',
'http://gmail.com',
'http://stackru.com',
'http://github.com',
'http://heroku.com',
'http://djangoproject.com',
'http://rubyonrails.org',
'http://basecamp.com',
'http://trello.com',
'http://yiiframework.com',
'http://shopify.com',
'http://airbnb.com',
'http://instagram.com',
'http://snapchat.com',
'http://youtube.com',
'http://baidu.com',
'http://yahoo.com',
'http://live.com',
'http://linkedin.com',
'http://yandex.ru',
'http://netflix.com',
'http://wordpress.com',
'http://bing.com',
]
start = time.time()
async def fetch(url):
browser = await launch(headless=True, args=['--no-sandbox'])
page = await browser.newPage()
await page.goto(f'{url}', {'waitUntil': 'load'})
await page.screenshot({'path': f'img/{urlparse(url)[1]}.png'})
await browser.close()
async def run():
tasks = []
for url in WEBSITE_LIST:
task = asyncio.ensure_future(fetch(url))
tasks.append(task)
responses = await asyncio.gather(*tasks)
#print(responses)
#asyncio.get_event_loop().run_until_complete(fetch('http://yahoo.com'))
loop = asyncio.get_event_loop()
future = asyncio.ensure_future(run())
loop.run_until_complete(future)
print(f'It took {time.time()-start} seconds.')
1 ответ
Согласно исходному коду pyppeteer, он использует подпроцесс без каналов для управления процессами Chromium и веб-сокеты для связи, поэтому он асинхронный.
У вас есть 31 сайт, тогда у вас будет 31+1 процессов. Таким образом, если у вас нет ЦП с 32 ядрами (могут быть также потоки, системные процессы, блокировки, гиперпоточность и все другие факторы, влияющие на результат, так что это просто неточный пример), он не будет полностью выполняться параллельно, Таким образом, узким местом, на мой взгляд, является открытие браузеров процессором, рендеринг веб-страниц и сброс в изображения. Использование executor не поможет.
Тем не менее, это все еще асинхронно. Это означает, что ваш процесс Python не заблокирован, вы все равно можете запускать другой код или одновременно ожидать сетевых результатов. Только когда процессор полностью загружен другими процессами, процессу Python становится труднее "украсть" время процессора.