☰
Selenium 装驱动太麻烦?Playwright 入门指南:Python 网页自动化新标准
2026/9/27 9:07:26 网站建设 项目流程

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+。同样建议用虚拟环境隔离:

python-mvenv .venvsource.venv/bin/activate# Windows 用 .venv\Scripts\activate# 第一步:装 Python 包pipinstallplaywright# 第二步:下载浏览器内核(约 100~300MB,只需执行一次)playwrightinstallchromium

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

# 使用国内镜像加速下载PLAYWRIGHT_DOWNLOAD_HOST=https://cdn.npmmirror.com/binaries/playwright playwrightinstallchromium

验证安装:

# check_env.pyfromplaywright.sync_apiimportsync_playwrightwithsync_playwright()asp:browser=p.chromium.launch(headless=True)page=browser.new_page()page.goto("https://example.com")print("页面标题:",page.title())browser.close()

能打印出Example Domain就说明环境没问题。

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

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

# shot.pyfromplaywright.sync_apiimportsync_playwrightwithsync_playwright()asp:# 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()拿到元素句柄,所有操作都基于它:

# 下面几种写法等价,选你顺手的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 说再见

fromplaywright.sync_apiimportexpect# 断言元素可见(默认超时 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() == ...更可靠,因为它会轮询等待而不是一次性判断。需要改全局超时可以这样:

page.set_default_timeout(15000)# 所有操作默认最多等 15 秒

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

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

withsync_playwright()asp: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 填表单与键盘鼠标

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 文件上传与下载

# 上传:直接给本地路径,不用再找系统文件框page.set_input_files("input[type=file]","report.xlsx")# 下载:必须用 expect_download 包住触发动作withpage.expect_download()asdl:page.get_by_text("导出报表").click()download=dl.value download.save_as("data/export.xlsx")

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

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

defblock_images(route):ifroute.request.resource_typein("image","font","media"):route.abort()else:route.continue_()page.route("**/*",block_images)page.goto("https://news.example.com")

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

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

# crawl_demo.pyfromplaywright.sync_apiimportsync_playwright,expect BASE="https://example.com"defmain():withsync_playwright()asp: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()# 等到跳转完成,不要用 sleepexpect(page).to_have_url(f"{BASE}/dashboard")# 2. 抓多页列表rows=[]forpage_noinrange(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()foritinitems: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()

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

ctx=browser.new_context(storage_state="auth.json")

七、和 Selenium 怎么选

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

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

八、常见坑与解决办法

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

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

frame=page.frame_locator("iframe#login-frame")frame.get_by_role("button",name="登录").click()

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

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

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

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

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。

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

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询