7
Playwright 现代自动化
Playwright: Faster & More Reliable
Playwright 是微软出品的现代浏览器自动化,比 Selenium 更快更稳,自动等待,支持 Chromium/Firefox/WebKit。新项目优先选它。
安装与第一个脚本
pip install playwright
playwright install # 下载浏览器,第一次要等一会
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://www.example.com")
print(page.title())
browser.close()
定位器 Locator:自动等待
# locator() 是"活的",每次操作自动等元素出现
page.goto("https://example.com")
# 点击、填表,不用手动写 wait_for
page.locator("#search").fill("Python")
page.locator("button[type=submit]").click()
# 读文本
title = page.locator(".result-title").text_content()
# 等某个选择器出现(显式)
page.wait_for_selector(".loaded", timeout=5000)
异步 API
from playwright.async_api import async_playwright
async def main():
async with async_playwright() as p:
browser = await p.chromium.launch()
page = await browser.new_page()
await page.goto("https://example.com")
await browser.close()
import asyncio
asyncio.run(main())
鼠标与键盘操作
# 鼠标
page.click("#btn") # 单击
page.dblclick("#btn") # 双击
page.hover("#menu") # 悬停
page.mouse.move(100, 200) # 移动鼠标到坐标
# 键盘
page.fill("#input", "hello")
page.keyboard.press("Enter")
page.keyboard.type("hello") # 逐字输入
# 拖拽
page.drag_and_drop("#source", "#target")
异步 API:高并发场景
# Playwright 异步 API,和 aiohttp 搭配
async def crawl_all(urls):
async with async_playwright() as p:
browser = await p.chromium.launch()
async def one(url):
page = await browser.new_page()
await page.goto(url)
title = await page.title()
await page.close()
return title
results = await asyncio.gather(*[one(u) for u in urls])
await browser.close()
return results
Playwright 常用操作速查
| 操作 | 代码 |
| 打开页面 | page.goto(url) |
| 点击 | page.locator(sel).click() |
| 填表 | page.locator(sel).fill("text") |
| 读文本 | page.locator(sel).text_content() |
| 读属性 | page.locator(sel).get_attribute("href") |
| 等元素 | page.wait_for_selector(sel) |
| 截图 | page.screenshot(path="a.png") |
| 执行 JS | page.evaluate("() => document.title") |
网络拦截与截图
# 拦截请求:拦截图片加速
async def block_images(route):
if route.request.resource_type == "image":
await route.abort()
else:
await route.continue()
page.route("**/*", block_images)
# 截图和 PDF
page.screenshot(path="page.png")
page.pdf(path="page.pdf") # 仅 Chromium
反检测:别被网站认出是机器人
现代网站有风控,会查"你到底是不是真浏览器"。直接 launch() 启动的 Chromium 自带几个破绽,容易被识别。Playwright 比 Selenium 隐蔽得多,但要过严的风控仍需主动抹平指纹。
论网站在查什么破绽
最经典的破绽:navigator.webdriver 在自动化浏览器里是 true,真用户是 false。还有 Headless 特有的 UA、缺插件、缺失的图形指纹。应对三板斧:改启动参数、注入脚本抹掉 webdriver、用贴近真人的 UA。
降低被识别概率的启动配置
from playwright.sync_api import sync_playwright
with sync_playwright() as p:
browser = p.chromium.launch(
headless=True,
args=[
"--disable-blink-features=AutomationControlled", # 关键:关掉自动化标记
"--no-sandbox",
],
)
context = browser.new_context(
user_agent="Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0 Safari/537.36",
viewport={"width": 1280, "height": 800},
locale="zh-CN",
)
# 注入脚本:把 navigator.webdriver 改成 undefined
context.add_init_script("Object.defineProperty(navigator, 'webdriver', {get: () => undefined})")
page = context.new_page()
page.goto("https://bot.sannysoft.com/") # 这个站专门测自动化指纹,自己玩时用
browser.close()
防坑:反检测不是万能的
大厂风控(行为分析、TLS 指纹、设备指纹)很难纯靠改参数绕过,真要硬刚得商用打码/住宅代理。正道还是优先走官方 API——前面"API 优先原则"说过,找 JSON 接口直接 requests,既快又不会被反自动化指纹拦住。反检测只是兜底。
练习:反检测小测(点开对答案)
问:为什么 --disable-blink-features=AutomationControlled 是关键?
答:它让 Chromium 不在 navigator.webdriver 上暴露自动化身份,配合 add_init_script 双保险抹掉这个标记。这是网页端风控最常检查的一项,去掉后通过率显著提高。
录制神器 codegen:你点,它写
不知道怎么定位元素、不知道操作该写哪句?别背 API——Playwright 自带 codegen,你像正常人一样在浏览器里点鼠标,它把动作实时录成 Python 代码。新手最高效的入门姿势。
# 命令行敲这行,会弹出一个真实浏览器 + 一个录制窗口
playwright codegen https://example.com
# 你在浏览器里点哪、填什么,右边自动生成:
# page.goto("https://example.com")
# page.get_by_role("textbox").fill("Python")
# page.get_by_role("button", name="搜索").click()
# 还能录成异步版 / 其他语言,以及录整个操作过程成 trace
playwright codegen --target python-async https://example.com
用法:录完把生成的代码拷出来,再自己加解析、存库逻辑就行。配合 page.pause() 调试,边跑边观察。
完整案例:爬动态渲染的电商列表
# ecommerce.py —— 滚动加载 + 提取商品
with sync_playwright() as p:
browser = p.chromium.launch(headless=True)
page = browser.new_page()
page.goto("https://example-shop.com/products")
# 滚动到底部加载更多
for _ in range(5):
page.evaluate("window.scrollTo(0, document.body.scrollHeight)")
page.wait_for_timeout(1000)
# 提取所有商品
products = page.locator(".product-card").all()
for card in products:
name = card.locator(".name").text_content()
price = card.locator(".price").text_content()
print(name, price)
page.screenshot(path="shop.png")
browser.close()
运行输出
# 滚动加载 5 次,共抓到 120 个商品
# iPhone 15 Pro ¥7999.00
# 小米 14 ¥4299.00
# ...
# 截图已保存:shop.png
本章面试题 · Playwright
1.(概念题)Playwright 比 Selenium 好在哪?
查看答案
答案:① 自动等待(locator 不用手写 wait_for);② 多浏览器(Chromium/Firefox/WebKit);③ 网络拦截、截图、录屏内置;④ 异步 API 原生支持。API 更现代,测试更稳。
2.(概念题)playwright install 干嘛用的?
查看答案
答案:下载 Playwright 配套的浏览器二进制(Chromium 等)。Selenium 要自己装 ChromeDriver,Playwright 一条龙搞定。
3.(思考题)什么情况下用 Playwright 而不是 Scrapy?
查看答案
答案:页面必须执行 JS 才能看到数据、要登录、要交互(点按钮翻页)时用 Playwright。静态 HTML、纯批量抓数据用 Scrapy,快几个数量级。