使用Playwright异步代码遇NotImplementedError:求原因分析与解决方案
问题分析与解决方案
根本原因
- 同步sleep阻塞事件循环:异步函数中使用了
time.sleep()这个同步方法,会直接阻塞整个异步事件循环,导致Playwright的异步操作无法正常执行,最终触发NotImplementedError。 - 异常捕获类型错误:代码中捕获的
PlaywrightTimeout并非Playwright实际抛出的超时异常类型,无法正确处理超时场景,导致错误未被拦截而暴露。 - 重复初始化Playwright实例:每次重试都重新创建
async_playwright()上下文,不仅浪费资源,还可能因资源未正确释放引发异常。
修复后的代码
import asyncio from playwright.async_api import async_playwright from playwright._impl._errors import TimeoutError async def get_html(url, selector, sleep=5, retries=3): html = None # 将Playwright实例初始化移到循环外 async with async_playwright() as p: browser = await p.chromium.launch() for i in range(1, retries+1): # 替换为异步sleep await asyncio.sleep(sleep * i) try: page = await browser.new_page() await page.goto(url) print(await page.title()) html = await page.inner_html(selector) await page.close() break except TimeoutError: print(f"Timeout error on {url}, retry {i}/{retries}") await page.close() continue await browser.close() return html
关键修复点说明
- 用
await asyncio.sleep()替代time.sleep():异步sleep不会阻塞事件循环,保证Playwright的异步任务能正常调度。 - 修正异常捕获类型:使用Playwright官方定义的
TimeoutError,确保超时错误能被正确捕获并触发重试。 - 复用Playwright和浏览器实例:将
async_playwright()和browser的初始化移到循环外,避免重复创建资源,提升运行效率。
内容的提问来源于stack exchange,提问作者Fashola John
相关产品推荐
相关产品推荐

