Playwright打开新页面-expect_page()使用

在使用 Playwright 的 Python API 处理页面链接打开新页面时,可以使用 context.expect_page() 来捕获新打开的页面。这种方法适用于点击链接、按钮或其他操作导致新页面(如新标签或新窗口)打开的场景。

处理新页面的一般步骤

  1. 使用 context.expect_page()
    context.expect_page() 是一个异步方法,用于监听新页面的打开事件。它会等待新页面加载完成并返回新页面的 Page 对象。
  2. 触发新页面的事件
    通常是通过点击链接、按钮或其他交互操作触发新页面的打开。确保在调用 context.expect_page() 后立即执行触发操作。
  3. 获取新页面对象
    使用 await context.expect_page() 获取新页面对象,然后可以对其进行操作(如获取标题、内容或继续导航)。

代码示例

以下是一个典型的示例,展示如何处理点击链接后打开的新页面:

from playwright.async_api import async_playwright

async def main():
    async with async_playwright() as p:
        # 启动浏览器
        browser = await p.chromium.launch(headless=False)
        # 创建新的浏览器上下文
        context = await browser.new_context()
        # 打开一个页面
        page = await context.new_page()

        # 导航到目标网页
        await page.goto("https://example.com")

        # 使用 expect_page() 捕获新页面
        async with context.expect_page() as new_page_info:
            # 点击一个会打开新页面的链接
            await page.click('a[target="_blank"]')  # 假设链接有 target="_blank"

        # 获取新页面对象
        new_page = await new_page_info.value

        # 对新页面进行操作
        print(f"New page title: {await new_page.title()}")
        print(f"New page URL: {new_page.url}")

        # 关闭新页面
        await new_page.close()
        # 关闭浏览器
        await browser.close()

# 运行异步函数
import asyncio
asyncio.run(main())

关键点解释

  1. context.expect_page()
  • 这是一个上下文管理器,通常与 async with 一起使用。
  • 它会监听新页面的打开事件,并在新页面加载完成后返回一个 Page 对象。
  • 如果没有新页面打开,可能会抛出超时异常(默认超时为 30 秒,可通过 timeout 参数调整)。
  1. 触发新页面的操作
  • async with context.expect_page() 块中,必须执行触发新页面的事件(如 page.click())。
  • 常见的触发方式包括点击带有 target="_blank" 的链接、提交表单或执行 JavaScript(如 window.open())。
  1. 新页面操作
  • 获取新页面对象后,可以像操作普通页面一样调用 new_page 的方法,例如 new_page.title()new_page.urlnew_page.query_selector()
  1. 超时处理
  • 如果新页面没有按预期打开,可以通过设置 timeout 参数来控制等待时间:
    python async with context.expect_page(timeout=10000) as new_page_info: # 10秒超时 await page.click('a[target="_blank"]')
  1. 同步 API
  • 如果你使用的是 Playwright 的同步 API(playwright.sync_api),可以用 context.expect_page() 的同步版本,操作方式类似: from playwright.sync_api import sync_playwright with sync_playwright() as p: browser = p.chromium.launch(headless=False) context = browser.new_context() page = context.new_page() page.goto("https://example.com") with context.expect_page() as new_page_info: page.click('a[target="_blank"]') new_page = new_page_info.value print(f"New page title: {new_page.title()}") new_page.close() browser.close()</code></pre></li>

注意事项

  • 确保触发操作正确:确认点击的链接或操作确实会打开新页面。如果链接没有 target="_blank" 或通过 JavaScript 打开新窗口,expect_page() 可能不会捕获到新页面。
  • 新页面类型context.expect_page() 适用于新标签页或新窗口。如果是弹窗(如 alertprompt),需要使用 page.on("dialog", handler)
  • 上下文管理:新页面属于同一个 BrowserContext,因此会共享 cookies 和其他上下文状态。
  • 错误处理:建议添加异常处理来应对超时或页面未打开的情况:
  try:
      async with context.expect_page() as new_page_info:
          await page.click('a[target="_blank"]')
      new_page = await new_page_info.value
  except Exception as e:
      print(f"Error: {e}")

其他场景

  1. 处理多个新页面
    如果可能同时打开多个新页面,可以多次调用 context.expect_page(),但需要注意触发顺序和页面捕获的正确性。
  2. 检查新页面内容
    在获取新页面后,可以使用 new_page.wait_for_selector()new_page.wait_for_load_state() 确保页面加载完成:
    python await new_page.wait_for_load_state("domcontentloaded")

总结

context.expect_page() 是处理新页面打开的正确方法。确保在 async with 块中触发新页面事件,并通过返回的 Page 对象操作新页面。如果需要同步 API,操作方式类似。结合超时设置和错误处理,可以让代码更健壮。

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注