You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Playwright-Python报错‘Navigation failed because page was closed!’的排查

错误原因分析
  1. 单页面复用冲突:循环中复用同一个page对象连续调用goto,前一次导航的资源未完全释放、页面状态未重置时发起新导航,会导致页面上下文异常,触发页面关闭。
  2. 反爬机制触发:Google会检测自动化工具访问,短时间内频繁请求会被判定为机器人,直接关闭当前页面,导致后续goto操作报错。
  3. 未做状态校验与异常处理:未针对页面加载状态做校验,也没有捕获异常的逻辑,一旦页面因意外关闭,后续操作直接抛出错误。
正确实现方式

方案1:每个URL创建独立页面(推荐)

为每个请求创建新页面,彻底避免单页面状态冲突,同时添加反爬规避配置:

from playwright.sync_api import sync_playwright

urls = ['http://www.google.co.uk'] * 30
with sync_playwright() as p:
    # 启动浏览器时添加反爬规避参数
    browser = p.chromium.launch(
        headless=True,
        args=[
            "--disable-blink-features=AutomationControlled",
            "--no-sandbox",
            "--disable-setuid-sandbox"
        ]
    )
    # 创建独立浏览器上下文,隔离会话状态
    context = browser.new_context(
        user_agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36"
    )
    
    for i, url in enumerate(urls):
        print(i, url)
        page = context.new_page()
        try:
            # 等待页面加载完成,设置超时时间
            response = page.goto(url, timeout=30000, wait_until="networkidle")
            if not response.ok:
                print(f"请求失败,状态码:{response.status}")
                continue
            # 等待目标元素加载后再查询
            page.wait_for_selector('h1', timeout=10000)
            headers = page.query_selector_all('h1')
            print(f"找到{len(headers)}个h1标签")
        except Exception as e:
            print(f"处理URL {url}时出错:{str(e)}")
        finally:
            # 用完即关闭页面,释放资源
            page.close()
    # 依次关闭上下文和浏览器
    context.close()
    browser.close()

方案2:复用单页面但添加状态重置与异常处理

如果坚持复用单页面,需确保每次导航前后重置状态,并捕获异常:

from playwright.sync_api import sync_playwright

urls = ['http://www.google.co.uk'] * 30
with sync_playwright() as p:
    browser = p.chromium.launch(
        headless=True,
        args=["--disable-blink-features=AutomationControlled"]
    )
    page = browser.new_page(user_agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36")
    
    for i, url in enumerate(urls):
        print(i, url)
        try:
            # 导航前确保页面处于就绪状态
            page.wait_for_load_state("domcontentloaded")
            # 发起导航并等待网络空闲
            page.goto(url, wait_until="networkidle", timeout=30000)
            page.wait_for_selector('h1', timeout=10000)
            headers = page.query_selector_all('h1')
            print(f"找到{len(headers)}个h1标签")
            # 重置页面状态,避免残留缓存影响下一次请求
            page.reload(wait_until="networkidle")
        except Exception as e:
            print(f"处理URL {url}时出错:{str(e)}")
            # 出错后销毁当前页面,重新创建新页面
            page.close()
            page = browser.new_page(user_agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36")
    page.close()
    browser.close()
关键优化点
  • 反爬规避:通过--disable-blink-features=AutomationControlled隐藏自动化标识,自定义user_agent模拟真实浏览器请求。
  • 异常隔离:对每个请求单独捕获异常,出错时及时销毁异常页面,避免影响后续任务。
  • 状态管控:使用独立页面/上下文隔离请求状态,或复用页面时强制重置状态,避免跨请求污染。
  • 等待策略:使用wait_until="networkidle"和wait_for_selector确保页面元素加载完成后再执行查询操作。

内容的提问来源于stack exchange,提问作者Richard

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.06 14:50:33