选择器表达式
在上面的代码中,我们使用了 CSS 表达式(比如#button
)来选取元素。实际上,Playwright 还支持 XPath 和自己定义的两种简单表达式,并且是自动识别的。
通过文本选择元素,这是 Playwright 自定义的一种表达式 page.click("text=login") # 直接通过 id 选择 page.click("id=login") # 通过 CSS 选择元素 page.click("#search") # 除了常用的 CSS 表达式外,Playwright 还支持了几个新的伪类 # :has 表示包含某个元素的元素 page.click("article:has(div.prome)") # :is 用来对自身做断言 page.click("button:is(:text('sign in'), :text('log in'))") # :text 表示包含某个文本的元素 page.click("button:text('Sign in')") # 包含 page.click("button:text-is('Sign is')") # 严格匹配 page.click("button:text-matches('\w+')") # 正则 # 还可以根据方位匹配 page.click("button:right-of(#search)") # 右边 page.click("button:left-of(#search)") # 左边 page.click("button:above(#search)") # 上边 page.click("button:below(#search)") # 下边 page.click("button:near(#search)") # 50px 之内的元素 # 通过 XPath 选择 page.click("//button[@id='search'])") # 所有 // 或者 .. 开头的表达式都会默认为 XPath 表达式
对于 CSS 表达式,还可以添加前缀css=
来显式指定,比如说 css=.login
就相当于 .login
.
除了上面介绍的四种表达式以外,Playwright 还支持使用 >>
组合表达式,也就是混合使用四种表达式。
page.click('css=nav >> text=Login')
复用 Cookies 等认证信息
在 Puppeteer 中,复用 Cookies 也是一个老大难问题了。这个是 Playwright 特别方便的一点,他可以直接导出 Cookies 和 LocalStorage, 然后在新的 Context 中使用。
# 保存状态 import json storage = context.storage_state() with open("state.json", "w") as f: f.write(json.dumps(storage)) # 加载状态 with open("state.json") as f: storage_state = json.loads(f.read()) context = browser.new_context(storage_state=storage_state)
监听事件
通过 page.on(event, fn) 可以来注册对应事件的处理函数:
def log_request(intercepted_request): print("a request was made:", intercepted_request.url) page.on("request", log_request) # sometime later... page.remove_listener("request", log_request)
其中比较重要的就是 request 和 response 两个事件
拦截更改网络请求
可以通过 page.on("request") 和 page.on("response") 来监听请求和响应事件。
from playwright.sync_api import sync_playwright as playwright def run(pw): browser = pw.webkit.launch() page = browser.new_page() # Subscribe to "request" and "response" events. page.on("request", lambda request: print(">>", request.method, request.url)) page.on("response", lambda response: print("<<", response.status, response.url)) page.goto("https://example.com") browser.close() with playwright() as pw: run(pw)
其中 request 和 response 的属性和方法,可以查阅文档:https://playwright.dev/python/docs/api/class-request
通过 context.route, 还可以伪造修改拦截请求等。比如说,拦截所有的图片请求以减少带宽占用:
context = browser.new_context() page = context.new_page() # route 的参数默认是通配符,也可以传递编译好的正则表达式对象 context.route("**/*.{png,jpg,jpeg}", lambda route: route.abort()) context.route(re.compile(r"(\.png$)|(\.jpg$)"), lambda route: route.abort()) page.goto("https://example.com") browser.close()
其中 route 对象的相关属性和方法,可以查阅文档:https://playwright.dev/python/docs/api/class-route
灵活设置代理
Playwright 还可以很方便地设置代理。Puppeteer 在打开浏览器之后就无法在更改代理了,对于爬虫类应用非常不友好,而 Playwright 可以通过 Context 设置代理,这样就非常轻量,不用为了切换代理而重启浏览器。
context = browser.new_context( proxy={"server": "http://example.com:3128", "bypass": ".example.com", "username": "", "password": ""} )
杀手级功能:录制操作直接生成代码
Playwright 的命令行还内置了一个有趣的功能:可以通过录制你的点击操作,直接生成 Python 代码。
python -m playwright codegen http://example.com/
其他
除此之外,Playwright 还支持处理页面弹出的窗口,模拟键盘,模拟鼠标拖动(用于滑动验证码),下载文件等等各种功能,请查看官方文档吧,这里不赘述了。对于写爬虫来说,Playwright 的几个特性可以说是秒杀 Puppeteer/Pyppeteer:
- 官方同步版本的 API
- 方便导入导出 Cookies
- 轻量级设置和切换代理
- 支持丰富的选择表达式
快点用起来吧!