Selenium 装驱动太麻烦?Playwright 入门指南:Python 网页自动化新标准

Selenium 装驱动太麻烦?Playwright 入门指南:Python 网页自动化新标准

一、开头痛点:驱动、等待、玄学报错

做过网页自动化的同学,大概率被这三件事折磨过:

  • 装驱动 :chromedriver 的版本必须和本机 Chrome 严丝合缝,浏览器一自动升级,脚本第二天就 SessionNotCreatedException。
  • 等元素 :页面还没渲染完就 find_element,报 NoSuchElementException;于是满屏 time.sleep(3),慢且不稳。
  • 换浏览器:Selenium 要分别配 Chrome、Firefox、Edge 的驱动,环境一换全得重来。

Playwright 把这三点一次性解决了:自带浏览器 (一条命令下载,版本永远匹配)、操作自带自动等待 (不用手写 sleep)、一套 API 通吃 Chromium / Firefox / WebKit。它由微软团队维护,Python 版 API 设计得很干净,写起来比 Selenium 顺手不少。

二、环境准备:两条命令

Playwright 支持 Python 3.8+。同样建议用虚拟环境隔离:

bash 复制代码
python -m venv .venv
source .venv/bin/activate          # Windows 用 .venv\Scripts\activate

# 第一步:装 Python 包
pip install playwright

# 第二步:下载浏览器内核(约 100~300MB,只需执行一次)
playwright install chromium

第二步是很多新手卡住的地方------它下载的是 Playwright 自带的浏览器,不是你桌面上那个 Chrome,所以不存在版本对不上的问题。国内下载慢可以走镜像:

bash 复制代码
# 使用国内镜像加速下载
PLAYWRIGHT_DOWNLOAD_HOST=https://cdn.npmmirror.com/binaries/playwright playwright install chromium

验证安装:

python 复制代码
# check_env.py
from playwright.sync_api import sync_playwright

with 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 就说明环境没问题。

三、最小可运行示例:打开页面并截图

Playwright 有同步和异步两套 API,日常脚本用同步版最省心:

python 复制代码
# shot.py
from playwright.sync_api import sync_playwright

with sync_playwright() as p:
    # headless=True 表示无界面运行;调试时改成 False 能看到真实浏览器
    browser = p.chromium.launch(headless=True)
    page = browser.new_page(viewport={"width": 1280, "height": 800})

    page.goto("https://www.python.org/")
    # full_page=True 会截取整页长图,不只是可视区域
    page.screenshot(path="python_org.png", full_page=True)

    browser.close()

对比 Selenium,同样的功能少了驱动配置、少了显式等待,代码块从十几行压到十行以内。

四、核心概念:Locator、自动等待、上下文

4.1 Locator:定位元素的新写法

Playwright 推荐用 locator() 拿到元素句柄,所有操作都基于它:

python 复制代码
# 下面几种写法等价,选你顺手的
page.locator("button#submit").click()
page.locator("text=登录").click()
page.get_by_role("button", name="登录").click()      # 按语义角色,最稳
page.get_by_placeholder("请输入用户名").fill("admin")
page.get_by_text("下一步").click()

Locator 是惰性 的:写 page.locator(...) 时不会真的去查 DOM,只有执行 .click()、.fill() 时才查找,并且会自动等到元素可见、可点击、不被遮挡。这就是「自动等待」。

4.2 自动等待:和 time.sleep 说再见

python 复制代码
from playwright.sync_api import expect

# 断言元素可见(默认超时 5 秒,期间反复重试)
expect(page.get_by_text("提交成功")).to_be_visible(timeout=10000)

# 断言 URL 变化
expect(page).to_have_url("https://example.com/dashboard")

expect 是 Playwright 官方的断言工具,比 assert page.title() == ... 更可靠,因为它会轮询等待而不是一次性判断。需要改全局超时可以这样:

python 复制代码
page.set_default_timeout(15000)   # 所有操作默认最多等 15 秒

4.3 上下文:多开互不干扰的会话

context 相当于一个独立的浏览器会话(独立的 Cookie、缓存),比开多个 browser 省资源:

python 复制代码
with sync_playwright() as p:
    browser = p.chromium.launch()
    # 模拟移动端 + 中文环境
    ctx = browser.new_context(
        viewport={"width": 390, "height": 844},
        user_agent="Mozilla/5.0 (iPhone; CPU iPhone OS 17_0 like Mac OS X) AppleWebKit/605.1.15",
        locale="zh-CN",
    )
    page = ctx.new_page()
    page.goto("https://example.com")
    ctx.close()   # 关上下文,Cookie 一起清掉
    browser.close()

五、进阶用法:表单、上传、拦截

5.1 填表单与键盘鼠标

python 复制代码
page.get_by_label("用户名").fill("zhangsan")
page.get_by_label("密码").fill("secret123")
page.get_by_label("记住我").check()
page.get_by_role("combobox").select_option("beijing")
page.keyboard.press("Enter")

5.2 文件上传与下载

python 复制代码
# 上传:直接给本地路径,不用再找系统文件框
page.set_input_files("input[type=file]", "report.xlsx")

# 下载:必须用 expect_download 包住触发动作
with page.expect_download() as dl:
    page.get_by_text("导出报表").click()
download = dl.value
download.save_as("data/export.xlsx")

5.3 拦截请求:屏蔽图片提速

抓数据时图片、字体往往没用,直接拦掉能明显加速:

python 复制代码
def block_images(route):
    if route.request.resource_type in ("image", "font", "media"):
        route.abort()
    else:
        route.continue_()

page.route("**/*", block_images)
page.goto("https://news.example.com")

六、实战场景:自动登录并抓取列表(完整代码)

下面这个例子把上面几点串起来,带登录态抓取分页数据,并保存截图:

python 复制代码
# crawl_demo.py
from playwright.sync_api import sync_playwright, expect

BASE = "https://example.com"

def main():
    with sync_playwright() as p:
        browser = p.chromium.launch(headless=True)
        ctx = browser.new_context(locale="zh-CN")
        page = ctx.new_page()
        page.set_default_timeout(15000)

        # 1. 登录
        page.goto(f"{BASE}/login")
        page.get_by_label("账号").fill("your_account")
        page.get_by_label("密码").fill("your_password")
        page.get_by_role("button", name="登录").click()
        # 等到跳转完成,不要用 sleep
        expect(page).to_have_url(f"{BASE}/dashboard")

        # 2. 抓多页列表
        rows = []
        for page_no in range(1, 4):
            page.goto(f"{BASE}/items?page={page_no}")
            expect(page.locator(".item-row").first).to_be_visible()
            items = page.locator(".item-row").all()
            for it in items:
                rows.append({
                    "title": it.locator(".title").inner_text(),
                    "price": it.locator(".price").inner_text(),
                })
            print(f"第 {page_no} 页抓到 {len(items)} 条")

        # 3. 保存登录态,下次直接复用,省掉重复登录
        ctx.storage_state(path="auth.json")

        print("共抓取", len(rows), "条")
        browser.close()

if __name__ == "__main__":
    main()

下次运行时直接加载已保存的登录态:

python 复制代码
ctx = browser.new_context(storage_state="auth.json")

七、和 Selenium 怎么选

维度 Playwright Selenium
浏览器驱动 自带,一条命令安装 需手动下载、版本必须匹配
等待机制 操作自带自动等待 需自己写 WebDriverWait 或 sleep
多浏览器 一套 API 支持 Chromium/Firefox/WebKit 每个浏览器各自适配
录制脚本 playwright codegen 官方支持 依赖第三方插件
网络拦截 原生 page.route 需借助代理
生态与资料 较新,中文资料相对少 十年积累,资料最多、岗位要求常见

结论:新项目优先 Playwright ,效率和稳定性都更好;老项目或需要兼容既有 Selenium 资产的继续用 Selenium,两者并不互斥。

八、常见坑与解决办法

1)playwright install 卡住或超时 换国内镜像,见第二节。公司网络有代理时设置 HTTPS_PROXY 环境变量再执行。

2)locator.click() 超时 先确认是不是在 iframe 里。跨框架要先切进去:

python 复制代码
frame = page.frame_locator("iframe#login-frame")
frame.get_by_role("button", name="登录").click()

3)被网站识别为自动化 默认 headless 会带自动化特征,可以加启动参数缓解:

python 复制代码
browser = p.chromium.launch(
    headless=True,
    args=["--disable-blink-features=AutomationControlled"],
)

4)抓到的中文乱码 确认 new_context(locale="zh-CN"),并且写入文件时指定编码 encoding="utf-8",Windows 上尤其容易踩。

5)调试时看不到过程 打开录制,事后回看每一步:

python 复制代码
ctx.tracing.start(screenshots=True, snapshots=True)
# ... 你的操作 ...
ctx.tracing.stop(path="trace.zip")

用 playwright show-trace trace.zip 可以在浏览器里逐步回放。

九、总结与下一步

Playwright 的三个核心优势:自带浏览器 (告别驱动地狱)、自动等待 (告别满屏 sleep)、统一 API(一套代码跑三种内核)。如果你之前被 Selenium 的驱动和等待折腾过,换过来基本是纯收益。

下一步建议:

  1. 用 playwright codegen https://你的目标站点 录一遍,看看官方推荐的选择器怎么写;
  2. 把现有脚本里的 time.sleep 逐步替换为 expect(...) 断言;
  3. 需要并发时改用异步 API(from playwright.async_api import async_playwright)配合 asyncio.gather。

官方文档:playwright.dev/python/docs...

相关推荐
databook1 小时前
检测数据异常值的五种统计技术
python·数据挖掘·数据分析
海宇数科1 小时前
Python数据工程:利用海宇车型识别精准优化车险理赔合规体验
人工智能·python
小小张说故事1 小时前
不会前端怎么做数据网页?Streamlit 入门指南:几行 Python 变出可交互应用
python·数据可视化
子兮曰1 小时前
Laya 深度解析:421M 开源决策模型硬刚 Jev,33ms 背后藏了啥
前端·后端·python
卷无止境1 小时前
前沿部署工程师:当代码写到客户的办公室里
后端·python
卷无止境1 小时前
AI Agent权限管理,如何做到"敢用又稳"
后端·python
小小张说故事1 小时前
Seaborn 入门指南:让统计数据可视化更优雅
python·机器学习
小小张说故事1 小时前
Transformers 入门指南:用 Python 调用预训练大模型
python·机器学习
小小张说故事1 小时前
FastAPI 入门指南:用 Python 极速构建 API
python·机器学习