[1342]Playwright的page.on用法

@[toc]

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

基本语法

python 复制代码
page.on(event, callback)

常用事件类型

1. 监听网络请求

python 复制代码
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. 监听对话框

python 复制代码
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. 监听控制台消息

python 复制代码
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. 监听页面错误

python 复制代码
async def handle_page_error(error):
    print(f"页面错误: {error}")

page.on("pageerror", handle_page_error)

完整示例

python 复制代码
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:拦截和修改请求

python 复制代码
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:收集性能数据

python 复制代码
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:自动处理弹窗

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

page.on("dialog", handle_dialog)

移除事件监听器

python 复制代码
# 移除特定事件的所有监听器
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 页面加载完成时
domcontentloaded DOM内容加载完成时
framenavigated 框架导航完成时

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

相关推荐
donecoding6 小时前
命令行与图形界面的复制哲学:从 `cp a b` 说起
程序员·命令行
AgentBuilder6 小时前
768维的谎言:SOTA视觉模型为何输给7个数字?
人工智能·程序员
大怪v20 小时前
前端佬们!!AI大势已来,未来的上限取决你的独特气质!恭请批阅!!
前端·程序员·ai编程
程序员Agions1 天前
程序员武学修炼手册(二):进阶篇——小有所成,从能跑就行到知其所以然
前端·程序员
程序员Agions1 天前
程序员武学修炼手册(一):入门篇——初学乍练,从 Hello World 到能跑就行
程序员
PPPHUANG2 天前
Switch2Antigravity: 让 IntelliJ IDEA 与 Antigravity 无缝协作
程序员·intellij idea·vibecoding
zhouzhouya2 天前
码上星辰,人间烟火:我的2025
前端·程序员·代码规范
凌览2 天前
2026年1月编程语言排行榜|C#拿下年度语言,Python稳居第一
前端·后端·程序员
JOEH602 天前
🚀 别再用 Future.get() 傻等了!CompletableFuture 异步编排实战,性能提升 300%!
后端·程序员
程序员鱼皮2 天前
干掉 Claude Code,这个开源 AI 编程工具杀疯了?
前端·后端·计算机·ai·程序员