本文最后更新于 2026年7月12日 晚上
本文介绍 MCP Playwright 如何将 AI 助手与浏览器自动化结合,实现智能化的 Web 应用调试。
什么是 MCP Playwright MCP (Model Context Protocol) 是一种标准化的协议,允许 AI 助手与外部工具进行交互。Playwright 是微软开发的现代化浏览器自动化工具。
MCP Playwright 将两者结合,让 AI 助手能够:
核心优势 1. 智能化调试 AI 可以:
自动分析错误信息
智能选择最优的选择器
动态调整调试策略
自动生成调试报告
2. 完整的上下文感知 AI 可以看到:
当前页面 DOM 结构
控制台日志(console.log, error, warning)
网络请求和响应
页面截图和视频
localStorage/sessionStorage 状态
3. 高效的迭代循环 1 2 3
发现问题 → AI 分析 → 生成修复方案 → 自动验证 → 输出报告 ↓ ↑ └──────────── 快速迭代,无需手动干预 ──────────┘
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 每次调试都会生成: - 📸 关键步骤截图 - 📹 完整操作视频 - 📄 详细的 JSON 日志 - 📝 结构化的问题报告 ```bash 1 2 3 4 5 6 7 pip install playwright playwright install chromium playwright install chrome playwright install msedge
验证安装 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 1 2 3 4 5 6 7 8 from playwright.sync_api import sync_playwrightwith sync_playwright() as p: browser = p.chromium.launch(headless=True ) page = browser.new_page() page.goto("https://example.com" ) print (page.title()) browser.close()
预期输出:Example Domain
核心功能 1. 浏览器导航 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 1 2 3 4 5 6 7 8 page.goto("http://localhost:5173/login" ) page.wait_for_load_state("networkidle" ) page.wait_for_selector("#username" , timeout=5000 )
2. 元素定位与交互 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 1 2 3 4 5 6 7 8 9 page.locator('input[name="username"]' ) page.locator('text=忘记密码' ) page.locator('//button[contains(text(), "登录")]' ) page.fill('input[name="username"]' , 'admin' ) page.fill('input[name="password"]' , 'admin123' ) page.click('button[type="submit"]' )
3. 截图与录制 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 1 2 3 4 5 6 7 8 9 10 11 12 page.screenshot(path='debug_01_initial.png' , full_page=True ) element = page.locator('#error-message' ) element.screenshot(path='error_element.png' ) context = browser.new_context( record_video_dir='videos/' , record_video_size={'width' : 1920 , 'height' : 1080 } )
4. 日志捕获 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 console_messages = []def handle_console (msg ): console_messages.append({ 'type' : msg.type , 'text' : msg.text, 'location' : f"{msg.location.get('url' , '' )} :{msg.location.get('lineNumber' , '' )} " }) page.on("console" , handle_console) network_requests = []def handle_response (response ): network_requests.append({ 'url' : response.url, 'method' : response.request.method, 'status' : response.status, 'headers' : dict (response.headers) }) page.on("response" , handle_response)
5. JavaScript 执行 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 1 2 3 4 5 6 7 8 9 10 11 12 auth_data = page.evaluate("""() => { return { token: localStorage.getItem('token'), user: localStorage.getItem('user') }; }""" ) page.evaluate("""() => { document.body.style.backgroundColor = 'red'; }""" )
实战案例:登录问题排查 问题背景 用户报告无法登录系统,提示”登录失败,请检查用户名和密码”。
调试流程 Step 1: 创建调试脚本 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 from playwright.sync_api import sync_playwrightimport timeimport jsondef debug_login (): with sync_playwright() as p: browser = p.chromium.launch( headless=False , channel="chrome" , slow_mo=500 ) context = browser.new_context(viewport={'width' : 1920 , 'height' : 1080 }) page = context.new_page() console_messages = [] network_requests = [] page.on("console" , lambda msg: console_messages.append({ 'type' : msg.type , 'text' : msg.text })) page.on("response" , lambda res: network_requests.append({ 'url' : res.url, 'status' : res.status, 'method' : res.request.method })) page.goto('http://localhost:5173/login' ) page.wait_for_load_state('networkidle' ) time.sleep(2 ) page.screenshot(path='debug_01_initial.png' , full_page=True ) page.fill('input[name="username"]' , 'admin' ) page.fill('input[name="password"]' , 'admin123' ) time.sleep(1 ) page.click('button[type="submit"]' ) time.sleep(3 ) if '/login' in page.url: print ("❌ 仍在登录页面,登录可能失败" ) error_element = page.locator('.bg-red-50' ) if error_element.count() > 0 : error_text = error_element.inner_text() print (f"❌ 错误提示: {error_text} " ) else : print ("✅ 已跳转到首页,登录成功" ) debug_info = { 'console_messages' : console_messages[-20 :], 'network_requests' : [r for r in network_requests if 'api' in r['url' ]], 'current_url' : page.url, 'timestamp' : time.time() } with open ('debug_login_info.json' , 'w' , encoding='utf-8' ) as f: json.dump(debug_info, f, ensure_ascii=False , indent=2 ) browser.close()if __name__ == '__main__' : debug_login()
Step 2: 分析输出 发现的关键信息:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 1 2 3 4 5 6 [Console error ] Access to XMLHttpRequest at 'http://localhost:8000/api/v1/auth/login' from origin 'http://localhost:5173' has been blocked by CORS policy [Console error ] Failed to load resource: net::ERR_FAILED ❌ 错误提示: 登录失败,请检查用户名和密码
后端日志显示:
1 2 3 4 5 6 7 1 2 ValueError : password cannot be longer than 72 bytesFile "app/core/security.py" , line 26 , in verify_password
Step 3: 定位根本原因 通过综合分析:
❌ CORS 错误 - 实际是表象,请求被后端拒绝
❌ bcrypt 兼容性问题 - passlib 与新版 bcrypt 不兼容
✅ 根本原因 - 密码验证逻辑崩溃导致返回错误响应
Step 4: 实施修复 修改 backend/app/core/security.py:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 from passlib.context import CryptContext pwd_context = CryptContext(schemes=["bcrypt" ], deprecated="auto" )def verify_password (plain_password: str , hashed_password: str ) -> bool : return pwd_context.verify(plain_password, hashed_password)import bcryptdef verify_password (plain_password: str , hashed_password: str ) -> bool : try : return bcrypt.checkpw( plain_password.encode('utf-8' ), hashed_password.encode('utf-8' ) ) except Exception: return False
Step 5: 验证修复 重新运行调试脚本,确认:
✅ 无 CORS 错误
✅ 无控制台错误
✅ 成功跳转到首页
✅ localStorage 中有 token
最佳实践 1. 浏览器配置 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 1 2 3 4 5 6 7 8 9 10 11 browser = p.chromium.launch( headless=False , channel="chrome" , slow_mo=500 , args=[ '--no-sandbox' , '--disable-infobars' , '--disable-extensions' ] )
⚠️ 重要提醒:进程隔离原则
Playwright 必须启动独立的 Chrome 进程,严禁复用用户当前打开的浏览器!
原因:
🔒 权限边界 :AI 只能控制自己启动的进程,无法操作用户的浏览器
👤 用户隐私 :避免访问用户的个人浏览数据、登录状态等敏感信息
🛡️ 工作隔离 :防止自动化测试干扰用户的正常工作流程
🧹 资源清理 :测试完成后可以安全关闭,不留残留
2. 元素定位策略 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 page.locator('input[name="username"]' ) page.locator('#login-button' ) page.locator('[data-testid="submit-btn"]' ) page.locator('.btn.btn-primary' ) page.locator('text=登录' ) page.locator('//div[@class="form"]/input[1]' )
3. 等待策略 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 1 2 3 4 5 6 7 8 9 10 11 12 page.wait_for_load_state('networkidle' ) page.wait_for_selector('#element' , state='visible' ) page.wait_for_selector('#button' , state='enabled' ) time.sleep(5 )
4. 错误处理 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 1 2 3 4 5 6 7 8 9 10 11 try : page.goto('http://localhost:5173/login' , timeout=10000 )except TimeoutError: print ("❌ 页面加载超时" ) page.screenshot(path='error_timeout.png' ) raise except Exception as e: print (f"❌ 未知错误: {e} " ) page.screenshot(path='error_unknown.png' ) raise
常见问题 Q1: 浏览器启动失败 症状:
1 2 3 4 5 1 playwright._impl._errors.Error: BrowserType.launch: Executable doesn't exist
解决:
1 2 3 4 5 6 7 8 9 1 2 3 playwright install chromium playwright install chrome
Q2: 元素找不到 症状:
1 2 3 4 5 1 TimeoutError: locator.click: Timeout 30000 ms exceeded
解决:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 1 2 3 4 5 6 7 8 9 10 11 print (page.content()) page.screenshot(path='debug_current.png' ) element = page.locator('input[name="username"], input#username' ).first page.wait_for_selector('input[name="username"]' , timeout=10000 )
Q3: CORS 跨域错误 症状:
1 2 3 4 5 1 Access to XMLHttpRequest has been blocked by CORS policy
解决:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 1 2 3 4 5 6 7 8 9 10 11 12 BACKEND_CORS_ORIGINS = [ "http://localhost:5173" , "http://127.0.0.1:5173" ] context = browser.new_context( bypass_csp=True , ignore_https_errors=True )
总结 MCP Playwright 将 AI 助手与浏览器自动化结合,实现了智能化的 Web 应用调试。通过 AI 驱动的自动化调试、全面的上下文感知、高效的迭代循环和可复用的调试资产,大大提升了调试效率和质量。
核心优势:
行动建议:
相关资源:
💡 提示 :本文是基于实战经验总结的 MCP Playwright 使用指南,更多细节请参考完整的实战指南文档。