Playwright 爬虫教程 (2024 最新版)

1. Playwright 简介

Playwright 是微软在 2020 年初开源的新一代浏览器自动化工具,经过 4 年的发展已成为最流行的浏览器自动化工具之一。相比 Selenium 和 Puppeteer,Playwright 具有以下优势:

  • 多浏览器支持:Chromium、Firefox、WebKit 三大浏览器引擎
  • 跨平台支持:Windows、macOS、Linux 全平台支持
  • 现代化 API:简洁直观的 API 设计,内置自动等待机制
  • 移动端模拟:支持设备模拟和地理位置设置
  • 性能优越:比 Selenium 更快,比 Puppeteer 功能更全面
  • 活跃社区:持续更新,问题修复迅速

2. 安装与配置

系统要求

  • Python 3.8+
  • Windows/macOS/Linux 操作系统

安装步骤

pip install playwright
playwright install

安装完成后会自动下载 Chromium、Firefox 和 WebKit 浏览器,无需额外配置驱动。

注意:国内用户可使用清华镜像加速安装:

pip install playwright -i https://pypi.tuna.tsinghua.edu.cn/simple
PLAYWRIGHT_DOWNLOAD_HOST=https://npmmirror.com/mirrors/playwright playwright install

3. 基础用法

同步模式示例

from playwright.sync_api import sync_playwright

with sync_playwright() as p:
    # 启动Chromium浏览器
    browser = p.chromium.launch(headless=False)
    page = browser.new_page()
    
    # 导航到目标页面
    page.goto("https://www.baidu.com")
    
    # 获取页面标题
    print(f"页面标题: {page.title()}")
    
    # 截图保存
    page.screenshot(path="baidu.png")
    
    # 关闭浏览器
    browser.close()

异步模式示例

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://www.baidu.com")
        print(await page.title())
        await page.screenshot(path="baidu.png")
        await browser.close()

asyncio.run(main())

4. 代码生成工具

Playwright 提供强大的代码录制功能:

playwright codegen --target python -o script.py -b firefox

启动后会打开浏览器和代码窗口,所有操作会自动生成代码。

5. 移动端模拟

from playwright.sync_api import sync_playwright

with sync_playwright() as p:
    # iPhone 12 Pro模拟
    iphone = p.devices["iPhone 12 Pro"]
    browser = p.webkit.launch(headless=False)
    
    # 创建上下文
    context = browser.new_context(
        **iphone,
        geolocation={"latitude": 39.913904, "longitude": 116.39014},
        permissions=["geolocation"]
    )
    
    page = context.new_page()
    page.goto("https://maps.baidu.com")
    page.wait_for_load_state("networkidle")
    page.screenshot(path="location.png")
    browser.close()

6. 元素选择器

Playwright 支持多种元素定位方式:

# 文本选择
page.click("text=登录")

# CSS选择器
page.fill("#username", "admin")

# XPath
page.click("xpath=//button[@id='submit']")

# 组合选择器
page.click("article:has-text('Playwright')")
page.click("#nav-bar >> text=联系我们")

7. 核心API详解

页面导航

page.goto(url, timeout=30000)  # 导航到URL
page.go_back()  # 后退
page.go_forward()  # 前进
page.reload()  # 刷新

元素操作

page.click(selector)  # 点击
page.fill(selector, value)  # 输入文本
page.check(selector)  # 勾选复选框
page.select_option(selector, value)  # 选择下拉选项

等待机制

page.wait_for_selector(selector)  # 等待元素出现
page.wait_for_load_state("networkidle")  # 等待网络空闲
page.wait_for_timeout(3000)  # 强制等待

页面内容

content = page.content()  # 获取HTML源码
text = page.inner_text(selector)  # 获取元素文本
value = page.input_value(selector)  # 获取输入值

文件处理

page.screenshot(path="screenshot.png")  # 截图
page.pdf(path="page.pdf")  # 保存为PDF

8. 高级功能

网络拦截

# 阻止图片加载
page.route("**/*.{png,jpg,jpeg}", lambda route: route.abort())

# 修改响应
page.route("**/api/data", lambda route: route.fulfill(
    status=200,
    content_type="application/json",
    body=json.dumps({"data": "modified"})
))

事件监听

# 监听请求和响应
def log_response(response):
    print(f"响应: {response.url} {response.status}")

page.on("response", log_response)

多页面管理

# 获取所有页面
pages = context.pages

# 监听新页面
def handle_new_page(new_page):
    print(f"新页面打开: {new_page.url}")

context.on("page", handle_new_page)

文件下载

with page.expect_download() as download_info:
    page.click("a#download")
download = download_info.value
path = download.path()  # 临时文件路径
download.save_as("/path/to/save")  # 保存文件

9. 性能优化技巧

  1. 启用无头模式headless=True
  2. 复用浏览器上下文:避免频繁启动/关闭浏览器
  3. 合理使用等待:优先使用wait_for_selector而非固定等待
  4. 禁用不必要资源:拦截图片、样式表等非必要请求
  5. 并行处理:使用多线程/协程同时控制多个页面

10. 常见问题解决

Q: 元素点击失败?

  • 确保元素可见且可交互
  • 尝试page.click(selector, force=True)
  • 使用page.hover(selector)先悬停

Q: 页面加载超时?

  • 增加超时时间:page.goto(url, timeout=60000)
  • 检查网络连接
  • 确认目标网站无反爬机制

Q: 如何绕过验证码?

  • 使用第三方验证码识别服务
  • 配置浏览器指纹信息
  • 考虑人工介入处理

11. 实战案例

案例1:爬取动态渲染页面

with sync_playwright() as p:
    browser = p.chromium.launch()
    page = browser.new_page()
    page.goto("https://example.com/dynamic")
    
    # 等待数据加载
    page.wait_for_selector(".data-item")
    
    # 提取数据
    items = page.query_selector_all(".data-item")
    for item in items:
        print(item.inner_text())
    
    browser.close()

案例2:自动化表单提交

page.goto("https://example.com/login")
page.fill("#username", "testuser")
page.fill("#password", "password123")
page.click("#submit")

# 验证登录成功
assert "Welcome" in page.title()

案例3:无限滚动页面抓取

while True:
    # 滚动到底部
    page.evaluate("window.scrollTo(0, document.body.scrollHeight)")
    
    try:
        # 等待新内容加载
        page.wait_for_selector(".new-item", timeout=3000)
    except:
        break  # 没有新内容时退出
    
    # 处理新内容
    items = page.query_selector_all(".item")
    for item in items:
        print(item.inner_text())

12. 最佳实践

  1. 使用上下文管理器:确保资源正确释放
  2. 异常处理:捕获超时等异常情况
  3. 配置重用:保存cookies和本地存储
  4. 日志记录:记录关键操作和错误
  5. 定期维护:保持Playwright和浏览器版本更新

13. 资源推荐

通过本教程,您已经掌握了Playwright的核心功能和使用技巧。Playwright强大的功能和简洁的API使其成为现代网络爬虫和自动化测试的理想选择。