Playwright
Playwright Python
Playwright 浏览器自动化
Playwright 是微软推出的 web 自动化工具,相较于目前最常用的 Selenium,它仅用一个API即可自动执行Chromium、Firefox、WebKit等主流浏览器自动化操作。
https://playwright.dev/
https://github.com/microsoft/playwright
Playwright 是一个强大的自动化库,用于Web浏览器的自动化测试和爬虫。它支持 Chromium、Firefox 和 WebKit,并提供同步和异步API。
主要特点:
- 跨浏览器:在 Chromium、Firefox 和 WebKit 上运行测试。
- 跨平台:在 Windows、Linux 和 macOS 上运行。
- 支持无头(headless)和有头(headed)模式。
- 自动等待:自动等待元素出现、可操作等,减少人工等待代码。
- 强大的网络能力:可以拦截和修改网络请求。
- 模拟移动设备、地理位置等。
- 执行速度比 Selenium 快
playwright-python
microsoft / playwright-python
https://github.com/microsoft/playwright-python
安装 playwright 及浏览器驱动
pip 安装 playwright
pip install playwright
playwright --version
首次使用需要安装浏览器驱动
(1)安装全部浏览器驱动:
playwright install
(2)或者安装特定浏览器驱动:
playwright install chromium
playwright install firefox
playwright install webkit
Docker 中使用 playwright 创建浏览器驱动缓存层
在 docker 容器内使用时,为避免每次重新构建镜像后都需要重新下载浏览器驱动,可以在 Dockerfile 中提前下载浏览器驱动,创建 docker 缓存层:
# 先单独安装 playwright 并下载 chromium,建立 playwright+chromium 的缓存层,避免每次 requirements.txt 变化都要重新下载 chromium
RUN pip install playwright && python -m playwright install --with-deps chromium
# 先单独 COPY requirements.txt 和安装依赖,这样 requirements.txt 不变时能缓存依赖层。
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
基本概念
context 浏览器上下文
Playwright 中的 浏览器上下文(Browser Context) 用于 cookies、本地存储、缓存 等数据的隔离。
每个浏览器上下文(Browser Context)都是独立的会话环境,相互之间不会共享 cookies、本地存储等信息。
直接 browser.new_page()
使用 默认上下文
browser = await playwright.chromium.launch()
page = await browser.new_page() # 使用默认上下文
系统自动创建并管理一个默认的浏览器上下文,所有通过 browser.new_page() 创建的页面共享同一个上下文。
Cookies、本地存储、缓存等数据在页面间共享。
资源占用:轻量级,适合简单场景。
但页面间可能相互污染(例如一个页面修改 Cookie 会影响其他页面)。
显式创建上下文 browser.new_context()
browser = await playwright.chromium.launch()
context = await browser.new_context() # 创建独立上下文
page = await context.new_page() # 页面绑定到该上下文
每个上下文是独立的“隐身会话”。
上下文间完全隔离:Cookie、本地存储、缓存相互独立。
资源成本:每个上下文独立进程,占用更多资源。
可为不同上下文配置不同参数:
context = await browser.new_context(
user_agent="自定义UA",
viewport={"width": 1024, "height": 768},
proxy={"server": "http://proxy.example.com:8080"},
locale="zh-CN"
)
使用场景建议:
使用 browser.new_page()
默认上下文
- 简单脚本或单用户任务(无需环境隔离,例如,所有页面都在同一个用户会话下操作,共享相同的登录状态)
- 资源有限,希望节省内存和启动时间。
使用 browser.new_context()
独立上下文
- 当需要多个独立的会话,例如模拟多个用户同时操作,或者需要完全隔离的环境(如一个测试用例需要干净的上下文,避免相互影响)。
- 需要为不同的页面设置不同的上下文配置(例如不同的设备模拟、不同的权限设置、不同的代理等)。
- 需要模拟不同的用户登录状态(例如一个管理员和一个普通用户)。
- 在自动化测试中,通常每个测试用例都会创建一个新的上下文,以确保测试之间的隔离,避免状态泄漏。
page.goto() 打开页面
page.goto() 是 Playwright 中最核心的导航方法,用于将浏览器页面导航到指定 URLawait page.goto("https://example.com")
页面将导航到指定 URL 并等待页面加载完成
页面等待策略page.goto()
会等待页面达到特定加载状态后才返回,可通过 wait_until 参数控制。page.goto
默认使用 load
等待策略 page.goto("https://example.com", wait_until="load")
超时时间
使用 timeout 参数设置导航最大等待时间(毫秒)await page.goto("https://example.com", timeout=30000)
设置 30 秒超时
或者全局设置默认超时时间page.set_default_timeout(60000)
设置所有操作默认超时为 60 秒
自定义 HTTTP 头
可在导航时发送自定义 HTTP 头
await page.goto(
"https://example.com",
headers={
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64)",
"X-Custom-Header": "value"
}
)
自动重定向
page.goto() 会自动处理重定向链,可获取最终响应:
response = await page.goto("https://short.url/xyz")
print(f"实际导航到的 URL: {response.url}")
Referer 控制
使用 referer 参数设置来源页面:
await page.goto("https://secured-site.com", referer="https://referring-site.com")
POST 提交表单
使用 POST 方法提交表单数据:
await page.goto(
"https://example.com/login",
method="POST",
post_data={"username": "admin", "password": "123456"}
)
返回响应对象
page.goto() 返回一个响应对象,可获取响应信息:
response = await page.goto("https://example.com")
print(f"状态码: {response.status}")
print(f"标题: {response.headers['content-type']}")
print(f"响应文本: {await response.text()}")
page.route() 请求和响应拦截
page.route() 允许拦截并修改浏览器的网络请求和响应
阻止所有图片加载
# 阻止所有图片加载
await page.route("**/*.{png,jpg,jpeg,gif,svg,ico,woff,woff2,ttf}", lambda route: route.abort())
Playwright 页面等待策略
Playwright 中 goto
和 wait_for_load_state
函数中 wait_until
参数指定等待策略。
load(dom及静态资源)
load
默认策略 - 页面资源加载完成load
等待策略只加载静态资源(HTML, CSS, JS),不包括:AJAX 请求、动态生成的内容、Lazy loading 图片
触发时机: 当页面的 load 事件触发时
等待内容:
- DOM解析完成
- 所有同步资源加载完成(图片、样式表)
不等待:
- AJAX/XHR 异步请求
- 动态生成的内容
- Lazy loading 图片
- setTimeout/setInterval 回调
适用场景:
- 传统网页(非SPA)
- 静态内容页面
- 截图基础布局
domcontentloaded(仅dom)
domcontentloaded
触发时机: 当页面的 DOMContentLoaded 事件触发时
等待内容:
- HTML 文档解析完成
- 同步脚本执行完成
- 构建DOM树完成
不等待:
- 样式表加载
- 图片加载
- 异步脚本执行
适用场景:
- 表单操作
- 数据提取(只需DOM结构)
- 测试脚本执行
networkidle(无新网络请求)
networkidle
触发时机: 500ms内没有新的网络请求
等待内容:
- 所有资源加载完成
- 包含动态获取的资源
- 页面进入稳定状态
适用场景:
- 单页应用(React/Vue)
- 内容动态加载页面
- 需完整渲染的截图
commit(有HTTP相应即返回)
commit
触发时机: 收到HTTP响应头时
是最早完成的等待策略,此时页面内容可能尚未开始加载
适用场景:
- 性能基准测试
- 导航状态验证
- 极速爬虫场景(配合自定义等待)
Playwright Python 操作示例
Playwright 打开网页并截图
p.chromium.launch(headless=True)
启动 chrome 浏览器
参数 headless
headless=True
默认值,无头模式,不显示浏览器界面。headless=False
可视化模式,弹出浏览器界面
from playwright.sync_api import sync_playwright
def open_browser_and_screenshot():
with sync_playwright() as p:
# 启动浏览器 headless=False 可视化模式,弹出浏览器界面。默认值 true:无头模式,不显示浏览器界面。
browser = p.chromium.launch(headless=True)
# 打开新页面
page = browser.new_page()
# 导航到页面
page.goto("http://masikkk.com/")
# 截图保存
page.screenshot(path="masikkk_screenshot.png")
# 获取页面标题
print(page.title())
browser.close()
if __name__ == "__main__":
open_browser_and_screenshot()
Playwright 打开网页并截图(异步)
import asyncio
from playwright.async_api import async_playwright
async def open_browser_and_screenshot_async():
async with async_playwright() as p:
browser = await p.chromium.launch()
page = await browser.new_page()
await page.goto("http://devgou.com/tools/crawler")
await page.screenshot(path="devgou_screenshot.png")
await browser.close()
if __name__ == "__main__":
asyncio.run(open_browser_and_screenshot_async())
playwright-java
microsoft / playwright-java
https://github.com/microsoft/playwright-java
Playwright for Java
https://playwright.dev/java/
下一篇 PyCharm
页面信息
location:
protocol
: host
: hostname
: origin
: pathname
: href
: document:
referrer
: navigator:
platform
: userAgent
: