这是一份专为移动端阅读优化的 Playwright Python 教程,语言通俗、步骤清晰、示例完整。全程用同步模式演示(新手友好),关键处会标注异步写法差异。
一、准备工作:安装与环境配置
1. 安装核心包
打开命令行,执行以下命令:
bash
pip install playwright # 安装Playwright库
playwright install # 自动安装Chromium、Firefox、WebKit浏览器
2. 验证安装
创建test_install.py文件,运行以下代码:
python
from playwright.sync_api import sync_playwright
with sync_playwright() as p:
browser = p.chromium.launch(headless=False) # 启动Chrome浏览器(显示界面)
page = browser.new_page() # 新建标签页
page.goto("https://www.baidu.com") # 访问百度
print("页面标题:", page.title()) # 打印标题
browser.close() # 关闭浏览器
运行后能看到浏览器打开并显示百度页面,说明安装成功。
二、核心概念:Playwright 基础架构
Playwright 有四个核心对象,你必须牢记:
- Playwright 实例:入口点,控制所有浏览器
- Browser:浏览器实例(如 Chrome、Firefox)
- Context:浏览器上下文(相当于无痕窗口,可多个并行)
- Page:单个标签页(核心操作对象)
标准写法模板(记住这个格式):
python
from playwright.sync_api import sync_playwright
with sync_playwright() as p:
# 1. 启动浏览器(headless=False显示界面)
browser = p.chromium.launch(headless=False, slow_mo=1000) # slow_mo:慢动作,方便观察
# 2. 创建上下文(可选,用于多用户场景)
context = browser.new_context()
# 3. 新建页面
page = context.new_page()
# 4. 页面操作(核心代码写这里)
page.goto("https://example.com")
# 5. 关闭资源(with语句自动处理,可不写)
context.close()
browser.close()
三、页面操作:基础功能全掌握
1. 页面导航与等待
python
# 基础导航(自动等待页面加载完成)
page.goto("https://example.com", timeout=10000) # 超时10秒
# 前进/后退/刷新
page.go_back()
page.go_forward()
page.reload()
# 获取页面信息
print("URL:", page.url) # 当前网址
print("标题:", page.title()) # 页面标题
print("内容:", page.content()) # 完整HTML内容
2. 截图与 PDF 导出
python
# 截取整个页面
page.screenshot(path="full_page.png", full_page=True)
# 截取特定元素
page.locator("h1").screenshot(path="element.png")
# 导出PDF(仅Chrome支持)
page.pdf(path="page.pdf", format="A4")
四、元素定位:精准找到页面元素
这是 Playwright 最强大的功能之一,推荐使用Locator API(自动等待元素加载)。
1. 推荐定位方式(按优先级排序)
| 方法 | 用途 | 示例 |
|---|---|---|
| get_by_role | 按角色定位(最推荐,符合无障碍标准) | page.get_by_role ("button", name="搜索") |
| get_by_text | 按文本内容定位 | page.get_by_text ("登录") |
| get_by_label | 按表单标签定位 | page.get_by_label ("用户名") |
| get_by_placeholder | 按输入框提示定位 | page.get_by_placeholder ("请输入密码") |
| get_by_test_id | 按测试 ID 定位(推荐开发添加) | page.get_by_test_id("submit-btn") |
2. 传统定位方式(兼容旧代码)
python
# CSS选择器(最常用)
page.locator("input#kw") # ID选择器
page.locator(".result-title") # 类选择器
page.locator("div > a") # 层级选择器
# XPath选择器(复杂场景)
page.locator("//input[@name='username']")
3. 定位示例
python
from playwright.sync_api import sync_playwright
with sync_playwright() as p:
browser = p.chromium.launch(headless=False)
page = browser.new_page()
page.goto("https://www.baidu.com")
# 1. 按角色定位搜索框并输入内容
search_box = page.get_by_role("textbox", name="百度搜索")
search_box.fill("Playwright教程") # 填充内容
# 2. 按文本定位搜索按钮并点击
search_btn = page.get_by_text("百度一下")
search_btn.click()
# 3. 等待结果加载并打印第一个结果标题
page.wait_for_load_state("networkidle") # 等待网络空闲
first_result = page.locator(".result-op a:first-child")
print("第一个结果:", first_result.text_content())
browser.close()
五、交互操作:模拟用户行为
1. 输入操作
python
# 填充内容(推荐,自动清空原有内容)
page.get_by_label("用户名").fill("test_user")
# 逐字输入(模拟真实打字,delay:毫秒间隔)
page.get_by_label("密码").type("secret123", delay=100)
# 清空输入框
page.get_by_label("搜索").clear()
2. 点击与选择
python
# 普通点击
page.get_by_text("提交").click()
# 双击/右键点击
page.locator(".item").dblclick()
page.locator(".menu").click(button="right")
# 复选框/单选框
page.get_by_label("同意条款").check()
page.get_by_label("男").check()
# 下拉框选择
page.get_by_label("城市").select_option(value="beijing") # 按值选择
page.get_by_label("城市").select_option(label="上海") # 按文本选择
page.get_by_label("城市").select_option(index=3) # 按索引选择
3. 键盘与鼠标操作
python
# 键盘操作(按Enter键)
page.keyboard.press("Enter")
# 组合键(Ctrl+A全选,然后删除)
page.keyboard.press("Control+A")
page.keyboard.press("Backspace")
# 鼠标悬停
page.locator(".dropdown").hover()
# 拖拽操作(从元素A拖到元素B)
page.locator("#source").drag_to(page.locator("#target"))
4. 交互示例:模拟登录流程
python
from playwright.sync_api import sync_playwright
with sync_playwright() as p:
browser = p.chromium.launch(headless=False)
page = browser.new_page()
page.goto("https://example.com/login")
# 填写登录表单
page.get_by_label("用户名").fill("admin")
page.get_by_label("密码").fill("123456")
page.get_by_label("记住我").check()
page.get_by_role("button", name="登录").click()
# 验证登录成功
page.wait_for_url("**/dashboard") # 等待跳转到仪表盘
print("登录成功!")
browser.close()
六、等待机制:告别不稳定脚本
Playwright 最强大的特性之一:自动等待。所有操作前都会自动等待元素可见、可交互,无需手动添加 sleep。
1. 自动等待(默认启用)
python
# 自动等待搜索框出现并可输入
page.get_by_label("搜索").fill("Playwright")
# 自动等待按钮可点击
page.get_by_text("搜索").click()
2. 显式等待(复杂场景)
python
# 等待元素可见
page.locator(".success-message").wait_for(state="visible")
# 等待页面加载完成
page.wait_for_load_state("load") # 基本加载完成
page.wait_for_load_state("networkidle") # 网络空闲(推荐)
# 等待自定义条件
page.wait_for_function("() => document.title.includes('成功')")
七、高级功能:解锁更多可能性
1. 网络请求拦截与模拟
python
from playwright.sync_api import sync_playwright
def handle_route(route):
"""拦截并修改网络请求"""
if "api/data" in route.request.url:
# 返回模拟数据
route.fulfill(
status=200,
json={"name": "测试数据", "value": 123}
)
else:
route.continue_() # 其他请求正常放行
with sync_playwright() as p:
browser = p.chromium.launch(headless=False)
page = browser.new_page()
# 启用请求拦截
page.route("**/*", handle_route)
page.goto("https://example.com")
browser.close()
2. 移动端模拟
python
from playwright.sync_api import sync_playwright
with sync_playwright() as p:
# 模拟iPhone 12
iphone_12 = p.devices["iPhone 12"]
context = p.chromium.launch_persistent_context(
"", # 本地目录,用于保存缓存
**iphone_12,
headless=False
)
page = context.new_page()
page.goto("https://m.baidu.com") # 访问移动端网站
page.touchscreen.tap(50, 100) # 模拟触屏点击
context.close()
3. 执行 JavaScript 代码
python
python
# 执行简单JS并获取结果
width = page.evaluate("() => window.innerWidth")
print("窗口宽度:", width)
# 传递参数给JS
result = page.evaluate("(a, b) => a + b", 10, 20)
print("计算结果:", result)
# 操作页面元素
page.evaluate("document.querySelector('h1').style.color = 'red'")
4. 处理弹窗与 iframe
python
# 处理alert弹窗
page.on("dialog", lambda dialog: dialog.accept()) # 自动接受弹窗
# 处理iframe
frame = page.frame_locator("iframe[name='payment']")
frame.get_by_label("信用卡号").fill("4111 1111 1111 1111")
八、网络监听:实时捕获、分析接口数据
这是 Playwright 爬虫、接口调试、自动化测试 必备功能!作用:监控浏览器所有网络请求(接口、图片、JS 等),捕获请求 URL、参数、请求头、响应数据,无需抓包工具。
1. 基础监听:捕获所有网络请求
最简单用法,打印浏览器发出的所有请求信息
python
from playwright.sync_api import sync_playwright
with sync_playwright() as p:
browser = p.chromium.launch(headless=False)
page = browser.new_page()
# ========== 核心:注册网络监听 ==========
# 监听请求发送
def on_request(request):
# 过滤:只打印接口请求,忽略图片/样式
if request.resource_type in ["xhr", "fetch"]:
print(f"请求地址:{request.url}")
print(f"请求方式:{request.method}")
print("-"*50)
# 监听响应返回
def on_response(response):
if response.resource_type in ["xhr", "fetch"]:
print(f"响应状态:{response.status} | 地址:{response.url}")
# 绑定监听事件
page.on("request", on_request)
page.on("response", on_response)
# 测试页面
page.goto("https://www.baidu.com")
page.get_by_role("textbox", name="百度搜索").fill("Playwright")
page.get_by_text("百度一下").click()
page.wait_for_timeout(3000) # 等待请求完成
browser.close()
2. 精准监听:提取接口 JSON 数据(实战首选)
直接获取接口返回的业务数据,爬虫 / 测试必用
python
from playwright.sync_api import sync_playwright
import json
with sync_playwright() as p:
browser = p.chromium.launch(headless=False)
page = browser.new_page()
# 监听并解析接口响应数据
def on_response(response):
# 只监听百度搜索的接口
if "suggestion" in response.url and response.status == 200:
print("抓到目标接口!")
# 获取JSON数据
data = response.json()
print("接口返回数据:", json.dumps(data, ensure_ascii=False))
page.on("response", on_response)
# 执行搜索
page.goto("https://www.baidu.com")
page.get_by_role("textbox", name="百度搜索").fill("网络监听")
page.wait_for_timeout(3000)
browser.close()
3. 监听请求参数(POST/GET 参数)
获取接口提交的参数,用于调试和复现请求
python
def on_request(request):
# 监听POST接口
if request.method == "POST" and "api" in request.url:
print("请求头:", request.headers)
print("请求参数:", request.post_data) # POST数据
print("GET参数:", request.params) # GET参数
page.on("request", on_request)
4. 监听 + 拦截:一站式控制网络
结合路由,既监听又修改请求(进阶)
python
# 先监听,再拦截修改
def handle_route(route):
print(f"拦截请求:{route.request.url}")
route.continue_()
page.route("**/*", handle_route)
九、实战案例:百度搜索完整流程
以下是一个完整的自动化脚本,包含所有核心操作:
python
from playwright.sync_api import sync_playwright, expect
def test_baidu_search():
with sync_playwright() as p:
# 1. 启动浏览器
browser = p.chromium.launch(headless=False, slow_mo=500)
page = browser.new_page()
try:
# 2. 访问百度
page.goto("https://www.baidu.com", timeout=15000)
expect(page).to_have_title("百度一下,你就知道") # 断言标题
# 3. 搜索Playwright
search_box = page.get_by_role("textbox", name="百度搜索")
search_box.fill("Playwright Python教程")
page.get_by_text("百度一下").click()
# 4. 等待结果并验证
page.wait_for_load_state("networkidle")
expect(page.locator(".result-op")).to_have_count(10) # 断言有10个结果
# 5. 点击第一个结果
first_result = page.locator(".result-op a:first-child")
first_result.click()
# 6. 验证新页面
page.wait_for_url("**/playwright/**")
print("搜索并打开结果成功!")
except Exception as e:
print("出错了:", e)
page.screenshot(path="error.png") # 出错时截图
finally:
browser.close()
test_baidu_search()
十、异步编程:提升执行效率
Playwright 支持异步模式,适合同时处理多个页面:
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()
await page.goto("https://example.com")
print(await page.title())
await browser.close()
asyncio.run(main())
十一、最佳实践:编写稳定可靠的脚本
- 优先使用 Locator API:自动等待,避免大部分超时问题
- 使用 role 定位器:比 CSS 选择器更稳定,不受页面结构变化影响
- 避免硬等待 :用
wait_for代替time.sleep() - 处理异常:使用 try-except 捕获错误并截图
- 复用浏览器上下文:多个测试用例共享一个 context,提升速度
常见问题解答
- Q:浏览器启动后立即关闭? A:确保使用
with语句或显式调用browser.close(),不要在异步代码中混用同步方法。 - **Q:元素定位不到?**A:检查选择器是否正确,尝试使用更稳定的 role 定位器,或等待元素加载完成。
- Q:如何调试脚本? A:添加
slow_mo=1000参数(慢动作),或使用page.pause()在指定位置暂停执行。
总结
- 网络监听核心:
page.on("request")监听请求、page.on("response")监听响应 - 实战用法:过滤接口、提取 JSON 数据、获取请求参数
- 适用场景:爬虫抓数据、接口调试、自动化测试验证接口