Playwright 使用教程
Playwright是微软开源的浏览器自动化工具, 支持多浏览器引擎, 提供Python、JavaScript等多语言API. 它通过真实浏览器渲染页面获取数据, 操作接近真实用户, 在数据采集方面可以有效规避反爬机制. 下面我将介绍如何使用这一工具.
- 官方文档: https://playwright.dev
- 官方仓库: https://github.com/microsoft/playwright 80K+ 个 star
什么是 Playwright?
- Web自动化测试工具, 也可以用来作为爬虫工具
- 通过真实浏览器渲染页面后获取数据, 对比通过 API 调用获取数据的方式速度会慢点, 但是简单粗暴, 接近真实用户浏览网页, 较难被反爬针对
工具对比
- Selenium: 基于 Webdriver, 需要中间层转发, 性能较差. 驱动安装麻烦
- Puppeteer: 谷歌出品, 基于Chrome DevTools Protocol(CDP), 性能高. 针对 Chrome 浏览器, 语言支持Javascript
- Playwright: 微软出品, Puppeteer 增强版, 接口与 Puppeteer 几乎一样. 社区活跃文档质量高, 容易上手, 支持多浏览器, 支持多语言(Javascript,Python,Java,C#), 自动管理浏览器安装, 支持Docker部署.
前置准备
test和lib模式
Playwright 支持两种代码模式, test 和lib 模式, test 模式对于测试方面会更加方便强大, 而我们用于爬虫更适合使用 lib 模式
安装
安装 Python 库
pip install playwright
安装浏览器
playwright install
交互模式(REPL)
Python 是解释型语言, 它不需要把整个文件代码编译后才能执行, 可以写一行代码执行一行, 这在开发阶段提供了极大的便利
在命令行输入 python 进入交互界面, 然后就可以一行一行输入代码
from playwright.sync_api import sync_playwright
playwright = sync_playwright().start()
browser = playwright.chromium.launch()
page = browser.new_page()
page.goto("https://playwright.dev/")
page.screenshot(path="example.png")
browser.close()
playwright.stop()
同步和异步
- Python 异步编程
- 异步函数需要在
def前加async - 每次调用异步函数需要在前面加
await main函数需要放在asyncio.run()里执行
- 异步函数需要在
- 可以开发阶段先在交互模式用同步代码边调试边写, 待验证没问题了改成异步代码
上面的代码在异步模式代码如下
import asyncio
from playwright.async_api import async_playwright, Playwright
async def run(playwright: Playwright):
chromium = playwright.chromium # or "firefox" or "webkit".
browser = await chromium.launch()
page = await browser.new_page()
await page.goto("http://example.com")
# other actions...
await browser.close()
async def main():
async with async_playwright() as playwright:
await run(playwright)
asyncio.run(main())
with 和 start
Python 的 with 语句可以自动管理资源的回收, 建议代码使用 with 语句, 交互模式使用 start()
# 用 with
with sync_playwright() as playwright:
run(playwright)
# 用 start
playwright = sync_playwright().start()
run(playwright)
playwright.stop() # 需要主动调用资源回收
类型注解
Python 是动态类型语言, 对象的类型在运行时才确定, 在写代码阶段, 编辑器可能因为没有足够的类型信息而无法进行类型补全, 如果把类型注解补上, 编辑器就能知道对象什么类型, 从而进行智能补全
async def run(playwright: Playwright):
Python 异常
Playwright 有些操作会抛出异常, 在 Python 中异常要用 try ... except 捕获, 不然会程序终止退出
try:
...
except Exception as e: # except Exception as e: 捕获特定异常
...
finally: # 可不需要
...
第一个代码
from playwright.sync_api import sync_playwright
playwright = sync_playwright().start()
browser = playwright.chromium.launch(headless=False)
context = browser.new_context()
page = context.new_page()
page.goto("https://example.com")
page.locator('p').all_inner_texts()
page.locator('a').click()
context.close()
browser.close()
playwright.stop()
Playwright
根对象, 使用 with 语句不用调用 stop() 方法
# 异步使用 with
async with async_playwright() as playwright
# 同步使用 start()
playwright = sync_playwright().start()
...
playwright.stop()
BrowserType
对应一个浏览器类型, 通过 Playwright 对象的属性获得
chromium = playwright.chromium
Browser
- 对应一个浏览器实例
- 通过
BrowserType对象的launch()方法创建Browser对象 launch()方法可以带上参数, 默认浏览器以无头模式启动, 在开发时可以设置参数为headless=False让浏览器可见, 生产爬取时需要去掉
browser = await chromium.launch(headless=False)
记得调用 close() 方法回收资源
await browser.close()
BrowserContext
context 的设计提供了一种隔离浏览器会话的机制, 不同的 context 不会共享 Cookies 和缓存, Browser 对象提供 new_context() 方法创建 BrowserContext 对象
context = await browser.new_context()
同样需要记得调用 close() 方法回收资源
await context.close()
一个 Browser 对象可以创建多个 BrowserContext 对象
context1 = await browser.new_context()
context2 = await browser.new_context()
Page
- 对应一个浏览器标签页
Page对象可以通过BrowserContext对象的new_page()方法创建, 也可以直接通过Browser对象的new_page()方法创建(自动在内部创建新的BrowserContext)
使用 goto() 方法请求URL
page.goto("https://example.com")
有时为了防止代码执行完浏览器直接关闭, 可以使用 pause() 方法暂停页面(需要设置参数headless=False)
await page.pause()
Locator
Locator 对象代表 Page 被选中的节点元素, Page 对象提供多种方法获取 Locator, 如 get_by_...(), query_selector() 方法, 推荐统一用 locator() 方法
page.locator('#id') # 根据id选择
page.locator('.class') # 根据class选择
page.locator('h1') # 根据元素类型选择
选中元素后可以像人工操作一样任意操作, Locator 提供了这些方法