[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() 可以让你更好地监控和控制页面的行为,特别是在调试和自动化测试中非常有用。

相关推荐
深蓝AI42 分钟前
Epic 摊牌了:Claude 和 Codex 在写 UE6 的代码,十年没修掉的 bug 被 AI 扫光
程序员·ai编程
高晶2 小时前
微信小程序实战:iOS 降级查询工具从零开发
微信·程序员
kyriewen21 小时前
我算了笔账:AI 编程工具一年烧掉两台 MacBook
前端·人工智能·程序员
爱勇宝1 天前
你可能成不了技术大佬,然后呢?
前端·后端·程序员
Hilaku1 天前
删了一个没用的 console.log,生产环境直接崩了!
前端·javascript·程序员
轻口味1 天前
我用 TRAE 做了个 Obsidian 插件,把掘金接进分发流水线(本文就是它发的)
人工智能·程序员
SimonKing1 天前
号外号外,Stream-Nexus推送项目支持集群部署了
java·后端·程序员
一不小心扯到淡2 天前
键盘演奏:我写了一个键盘音效引擎
程序员·github
清风微拂2 天前
别再用记事本看日志了:我给程序员做了个大日志查看器
程序员
kyriewen2 天前
别再用防抖做懒加载了:120 张图只加载出 4 张
前端·javascript·程序员