[1342]Playwright的page.on用法

59 阅读2分钟

@[toc]

Playwright 的 page.on() 方法用于监听页面的各种事件。这是一个非常强大的功能,可以监听网络请求、对话框、控制台消息等。

基本语法

page.on(event, callback)

常用事件类型

1. 监听网络请求

async def handle_request(request):
    print(f"请求: {request.method} {request.url}")

async def handle_response(response):
    if response.status == 200:
        print(f"响应: {response.status} {response.url}")
        # 可以获取响应内容
        # body = await response.body()

page.on("request", handle_request)
page.on("response", handle_response)

2. 监听对话框

async def handle_dialog(dialog):
    print(f"对话框类型: {dialog.type}")
    print(f"对话框消息: {dialog.message}")
    await dialog.accept()  # 接受对话框
    # 或者 await dialog.dismiss()  # 关闭对话框

page.on("dialog", handle_dialog)

3. 监听控制台消息

async def handle_console(msg):
    print(f"控制台 {msg.type}: {msg.text}")
    if msg.type == 'error':
        print(f"错误详情: {msg.location}")

page.on("console", handle_console)

4. 监听页面错误

async def handle_page_error(error):
    print(f"页面错误: {error}")

page.on("pageerror", handle_page_error)

完整示例

import asyncio
from playwright.async_api import async_playwright

async def main():
    async with async_playwright() as p:
        browser = await p.chromium.launch(headless=False)
        page = await browser.new_page()
        
        # 设置事件监听器
        async def handle_request(request):
            if request.resource_type == "xhr" or request.resource_type == "fetch":
                print(f"API请求: {request.method} {request.url}")
        
        async def handle_response(response):
            if response.status == 200 and "api" in response.url:
                print(f"API响应: {response.status} {response.url}")
                try:
                    json_data = await response.json()
                    print(f"响应数据: {json_data}")
                except:
                    pass
        
        async def handle_console(msg):
            if msg.type in ['error', 'warning']:
                print(f"控制台{msg.type}: {msg.text}")
        
        async def handle_dialog(dialog):
            print(f"弹出对话框: {dialog.message}")
            await dialog.accept()
        
        # 注册事件监听器
        page.on("request", handle_request)
        page.on("response", handle_response)
        page.on("console", handle_console)
        page.on("dialog", handle_dialog)
        
        # 导航到页面
        await page.goto("https://example.com")
        
        # 执行一些操作
        await page.click("button")
        
        await asyncio.sleep(5)
        await browser.close()

# 运行
asyncio.run(main())

实际应用场景

场景1:拦截和修改请求

async def handle_request(request):
    # 拦截图片请求
    if request.resource_type == "image":
        await request.abort()
    # 修改请求头
    elif "api" in request.url:
        headers = request.headers
        headers['Authorization'] = 'Bearer token'
        await request.continue_(headers=headers)
    else:
        await request.continue_()

await page.route("**/*", handle_request)

场景2:收集性能数据

responses = []

async def handle_response(response):
    if response.status == 200:
        timing = await response.request.timing()
        responses.append({
            'url': response.url,
            'status': response.status,
            'size': len(await response.body()),
            'timing': timing
        })

page.on("response", handle_response)

场景3:自动处理弹窗

async def handle_dialog(dialog):
    print(f"自动处理对话框: {dialog.message}")
    await dialog.accept()

page.on("dialog", handle_dialog)

移除事件监听器

# 移除特定事件的所有监听器
page.remove_listener("request", handle_request)

# 或者重新定义为一个空函数
async def empty_handler():
    pass

page.on("request", empty_handler)

注意事项

  1. 异步处理:所有事件处理函数都必须是异步的
  2. 性能影响:大量的事件监听可能会影响性能
  3. 内存泄漏:长时间运行的页面要注意移除不需要的监听器
  4. 错误处理:在事件处理函数中要做好异常处理

常用事件列表

事件类型描述
request发送网络请求时
response收到网络响应时
dialog出现JavaScript对话框时
console控制台输出消息时
pageerror页面发生JavaScript错误时
load页面加载完成时
domcontentloadedDOM内容加载完成时
framenavigated框架导航完成时

使用 page.on() 可以让你更好地监控和控制页面的行为,特别是在调试和自动化测试中非常有用。