python - Python:使用 asyncio 的 Pyppeteer
问题描述
我正在做一些测试,我想知道下面的脚本是否异步运行?
# python test.py It took 1.3439464569091797 seconds.
31(站点)x 1.34 = 41.54s - 所以它少了几秒钟,但理论上它应该只需要最长的请求?
# python test.py It took 28.129364728927612 seconds.
也许在这里打开浏览器不是异步的,我应该为此使用执行器?
# 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://stackoverflow.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.')
解决方案
根据pyppeteer源代码,它使用没有管道的子进程来管理Chromium进程,并使用websockets进行通信,因此它是异步的。
您有 31 个站点,那么您将有 31+1 个流程。所以除非你有一个 32 核的 CPU(可能还有线程、系统进程、锁、超线程和所有影响结果的不同因素,所以这只是一个不精确的例子),它不会完全并行执行. 因此,我认为瓶颈是 CPU 打开浏览器、渲染网页和转储图像。使用执行器无济于事。
但是,它仍然是异步的。这意味着,您的 Python 进程没有被阻塞,您仍然可以运行其他代码或同时等待网络结果。只是当 CPU 被其他进程完全加载时,Python 进程更难“窃取” CPU 时间。
推荐阅读
- ionic-framework - 未捕获的错误:模块 phonegap-nfc.NFC 不存在。(离子 NFC 插件)
- swift - 节点跟随 cameraNode 及其物理体
- ios - 这是在 Swift 中检查选项的最简洁的方法吗
- r - rjags 和 r2jags 之间的区别
- amazon-redshift - Redshift 对约束的评论
- javascript - 根据父页面上的按钮单击在子页面内加载 div
- uicollectionview - 如果项目使用 iOS12 SDK 在 Xcode 10 beta (10L176w) 中编译,则 UICollectionView 不能 `dequeueReusableCellWithReuseIdentifier`
- dart - 如何转换成双倍
- r - 使用 rpart(iris 数据集)预测回归树
- python - 当我使用 toastnotification 执行 python exe 时显示未找到 win10toast 分发