Python asyncio+playwright实现异步 I/O 操作,并发执行多个网络请求
配方很简单,绝对简单易懂,看代码——
首先加入一点asyncio:
import asyncio
async def fetch_data(url):
# 模拟网络请求,这里使用 asyncio.sleep 代替
await asyncio.sleep(3)
return f"Data from {url}"
async def main():
# 使用列表推导式创建多个异步任务
tasks = [fetch_data(f"https://cn.bing.com/images/search?q=cat&form=HDRSC2&first={i}") for i in range(5)]
# 使用 asyncio.gather() 来并发执行多个异步任务
results = await asyncio.gather(*tasks)
# 输出结果
for result in results:
print(result)
# 运行主函数
asyncio.run(main())
上面这段代码运行一下你会发现,fetch_data
这个函数先睡了3秒钟,然后嗖地一下出来5个结果,对,这其实是5个fatch_data
同时睡(约等于同时[doge]),然后醒过来返回结果,如果不用异步的话就是大家轮流睡,那得花上5*3=15秒,异步的一大优势就体现在这里了。
asyncio
库就是你的(专属)管家,用的时候基本思路就是需要异步的函数前面加async
告诉asyncio
这个是个异步函数,需要花时间等的操作前面加await
告诉asyncio
这里可以先执行一下然后等结果,等的过程中可以先忙别的。剩下的交给asyncio
,它会帮你统筹整个流程。
然后再加入playwright搅拌均匀:
import asyncio
# 从Playwright的异步API导入async_playwright函数,用于创建一个异步上下文,管理浏览器的生命周期
from playwright.async_api import async_playwright
# 定义一个异步函数fetch_page_title,打开一个新页面,导航到指定url,并获取页面标题
async def fetch_page_title(url, browser):
# 使用await关键字等待浏览器创建一个新的上下文(即浏览器会话的一个隔离环境)
context = await browser.new_context()
# 在该上下文中创建一个新的页面实例
page = await context.new_page()
# 使用await关键字等待页面导航到指定的URL
await page.goto(url)
# 使用await关键字等待页面加载完成并获取页面的标题
title = await page.title()
# 使用await关键字等待上下文关闭,释放相关资源
await context.close()
# 返回获取到的页面标题
return title
async def main():
# 使用async with语句创建一个异步上下文,启动Chromium浏览器
async with async_playwright() as p:
# 使用await关键字等待浏览器实例创建并启动
browser = await p.chromium.launch()
# 创建一个URL列表,用于搜索带有关键词"cat"的图片
urls = [f'https://cn.bing.com/images/search?q=cat&form=HDRSC2&first={i}' for i in range(5)]
# 使用列表推导式创建一系列异步任务,每个任务都是调用fetch_page_title函数来获取对应URL的页面标题
tasks = [fetch_page_title(url, browser) for url in urls]
# 使用await关键字和asyncio.gather函数来并发执行所有任务,并等待它们全部完成
titles = await asyncio.gather(*tasks)
# 遍历任务结果,并打印每个页面标题
for title in titles:
print(title)
# 使用await关键字等待浏览器实例关闭,释放相关资源
await browser.close()
asyncio.run(main())
以上,撒花