Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >Playwright: 比 Puppeteer 更好用的浏览器自动化工具

Playwright: 比 Puppeteer 更好用的浏览器自动化工具

作者头像
爬虫技术学习
发布于 2023-03-06 06:39:48
发布于 2023-03-06 06:39:48
3.5K00
代码可运行
举报
文章被收录于专栏:爬虫技术学习爬虫技术学习
运行总次数:0
代码可运行

在 Playwright 之前,我一般会使用 Selenium 或者 Puppeteer 来进行浏览器自动化操作。然而,Selenium 经常会有一些奇怪的 bug, Puppeteer 则是没有官方 Python 版,非官方版本也只有 async 版本,并且也是有一些奇怪的 bug. 另外,众所周知,Python 的 Async API 并不是那么好使。

Playwright 是微软出品的浏览器自动化工具,代码质量应该是有足够保证的。而且它还官方支持同步版的 Python API, 同时支持三大浏览器,所以赶紧切换过来了。

特别注意 Playwright 的拼写,别把中间的 "w" 丢了。

安装

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
pip install playwright==1.8.0a1  # 很奇怪,必须指定版本,不指定会安装到一个古老的版本
python -m playwright install  # 安装浏览器,此处国内网络可能会有问题(你懂的),请自行解决

基本使用

Playwright 支持 Firefox / Chrome / WebKit(Safari). 其中 webkit 最轻量了,所以没有什么特殊需求最好使用 webkit, 不要使用 chromium.

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
from playwright.sync_api import sync_playwright as playwright

with playwright() as pw:
    webkit = pw.webkit.launch(headless=False)
    context = webkit.new_context()  # 需要创建一个 context
    page = context.new_page()  # 创建一个新的页面
    page.goto("https://www.apple.com")
    print(page.content())
    webkit.close()

Playwright 官方推荐使用 with 语句来访问,不过如果你不喜欢的话,也可以用 pw.start() 和 pw.stop().

新概念:Context

和 Puppeteer 不同的是,Playwright 新增了 context 的概念,每个 context 就像是一个独立的匿名模式会话,非常轻量,但是又完全隔离。比如说,可以在两个 context 中登录两个不同的账号,也可以在两个 context 中使用不同的代理。

通过 context 还可以设置 viewport, user_agent 等。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
context = browser.new_context(
  user_agent='My user agent'
)
context = browser.new_context(
  viewport={ 'width': 1280, 'height': 1024 }
)
context = browser.new_context(
    http_credentials={"username": "bill", "password": "pa55w0rd"}
)

# new_context 其他几个比较有用的选项:
ignore_https_errors=False
proxy={"server": "http://example.com:3128", "bypass": ".example.com", "username": "", "password": ""}
extra_http_headers={"X-Header": ""}

context 中有一个很有用的函数context.add_init_script, 可以让我们设定在调用 context.new_page 的时候在页面中执行的脚本。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
# hook 新建页面中的 Math.random 函数,总是返回 42
context.add_init_script(script="Math.random = () => 42;")
# 或者写在一个文件里
context.add_init_script(path="preload.js")

还可以使用 context.expose_bindingcontext.expose_function 来把 Python 函数暴露到页面中,不过个人感觉还是使用 add_init_script 暴露 JS 函数方便一些。

和 Puppeteer 一样,Playwright 的核心概念依然是 page, 核心 API 几乎都是 page 对象的方法。可以通过 context 来创建 page.

页面基本操作

按照官网文档,调用 page.goto(url) 后页面加载过程:

  1. 设定 url
  2. 通过网络加载解析页面
  3. 触发 page.on("domcontentloaded") 事件
  4. 执行页面的 js 脚本,加载静态资源
  5. 触发 page.on("laod") 事件
  6. 页面执行动态加载的脚本
  7. 当 500ms 都没有新的网络请求的时候,触发 networkidle 事件

page.goto(url) 会跳转到一个新的链接。默认情况下 Playwright 会等待到 load 状态。如果我们不关心加载的 CSS 图片等信息,可以改为等待到 domcontentloaded 状态,如果页面是 ajax 加载,那么我们需要等待到 networkidle 状态。如果 networkidle 也不合适的话,可以采用 page.wait_for_selector 等待某个元素出现。不过对于 click 等操作会自动等待。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
page.goto(url, referer="", timeout=30, wait_until="domcontentloaded|load|networkidle")

Playwright 会自动等待元素处于可操作的稳定状态。当然也可以用 page.wait_for_* 函数来手工等待:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
page.wait_for_event("event", event_predict, timeout)
page.wait_for_function(js_function)
page.wait_for_load_state(state="domcontentloaded|load|networkidle", timeout)
page.wait_for_selector(selector, timeout)
page.wait_for_timeout(timeout)  # 不推荐使用

对页面的操作方法主要有:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
# selector 指的是 CSS 等表达式
page.click(selector)
page.fill(selector, value)  # 在 input 中填充值

# 例子
page.click("#search")

获取页面中的数据的主要方法有:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
page.url  # url
page.title()  # title
page.content()  # 获取页面全文
page.inner_text(selector)  # element.inner_text()
page.inner_html(selector)
page.text_content(selector)
page.get_attribute(selector, attr)

# eval_on_selector 用于获取 DOM 中的值
page.eval_on_selector(selector, js_expression)
# 比如:
search_value = page.eval_on_selector("#search", "el => el.value")

# evaluate 用于获取页面中 JS 中的数据,比如说可以读取 window 中的值
result = page.evaluate("([x, y]) => Promise.resolve(x * y)", [7, 8])
print(result) # prints "56"

选择器表达式

在上面的代码中,我们使用了 CSS 表达式(比如#button)来选取元素。实际上,Playwright 还支持 XPath 和自己定义的两种简单表达式,并且是自动识别的。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
# 通过文本选择元素,这是 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 还支持使用 >> 组合表达式,也就是混合使用四种表达式。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
page.click('css=nav >> text=Login')

复用 Cookies 等认证信息

在 Puppeteer 中,复用 Cookies 也是一个老大难问题了。这个是 Playwright 特别方便的一点,他可以直接导出 Cookies 和 LocalStorage, 然后在新的 Context 中使用。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
# 保存状态
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) 可以来注册对应事件的处理函数:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
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") 来监听请求和响应事件。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
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, 还可以伪造修改拦截请求等。比如说,拦截所有的图片请求以减少带宽占用:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
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 设置代理,这样就非常轻量,不用为了切换代理而重启浏览器。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
context = browser.new_context(
    proxy={"server": "http://example.com:3128", "bypass": ".example.com", "username": "", "password": ""}
)

杀手级功能:录制操作直接生成代码

Playwright 的命令行还内置了一个有趣的功能:可以通过录制你的点击操作,直接生成 Python 代码。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
python -m playwright codegen http://example.com/

Playwright 还有很多命令行功能,比如生成截图等等,可以通过 python -m playwright -h 查看。

其他

除此之外,Playwright 还支持处理页面弹出的窗口,模拟键盘,模拟鼠标拖动(用于滑动验证码),下载文件等等各种功能,请查看官方文档吧,这里不赘述了。对于写爬虫来说,Playwright 的几个特性可以说是秒杀 Puppeteer/Pyppeteer:

  1. 官方同步版本的 API
  2. 方便导入导出 Cookies
  3. 轻量级设置和切换代理
  4. 支持丰富的选择表达式

快点用起来吧!

参考

  1. https://playwright.dev/python/docs/core-concepts
本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2021-01-24,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 爬虫技术学习 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
Google设置新标签页默认地址
然后会有说明,一直点箭头就行了,最后出现这个页面,输入浏览器默认打开的地址,save保存即可
鱼找水需要时间
2023/02/16
2.6K0
Google设置新标签页默认地址
Infinity New Tab:重新定义你的Chrome新标签页
Infinity new tab 是一款实用又清新的 Chrome(谷歌浏览器)新标签页功能扩展,可以完美替代默认的新标签页。受插件作者邀请,我特意安装体验了一把 ,还是很不错的! 下面就分享一下,希
张戈
2018/03/23
2.4K0
Infinity New Tab:重新定义你的Chrome新标签页
【软件测试】自动化常用函数
web ⾃动化测试的操作核⼼是能够找到⻚⾯对应的元素,然后才能对元素进⾏具体的操作。常⻅的元素定位⽅式⾮常多,如 id,classname,tagname,xpath,cssSelector 常⽤的主要由 cssSelector 和 xpath
椰椰椰耶
2024/11/19
1910
【软件测试】自动化常用函数
软件测试/人工智能|教你轻松玩转Edge浏览器
提到Windows系统自带的浏览器,大家第一反应就是IE,对IE大家都是深恶痛绝的,然后大家就纷纷转向了Chrome和Firefox;应该说微软也是知道大家对IE的不满,痛定思痛之后,推出了基于 Chromium内核的新浏览器——Edge,我本来也是拒绝的,但是使用之后,就真香了,使用十分方便,功能十分强大,因此本文就来个大家介绍一下如何玩转edge浏览器。
霍格沃兹测试开发Muller老师
2023/12/14
3080
Edge搜索栏太方便了:历史记录、书签、标签页快速搜索!
Edge之前陆续推出了Edge Workspace、Edge垂直标签栏、Edge集锦等实用功能,可以看到Edge浏览器非常注重让用户能够有序处理自己30~50个打开的标签页,提高信息管理效率。
全网漫游指南
2024/01/31
4.3K0
Edge搜索栏太方便了:历史记录、书签、标签页快速搜索!
【插件】解放鼠标,让浏览器更智能
首先感谢大家参与这周的送书活动。已经给小助手微信发送好友请求的,不要着急,这两天会通过验证,并拉大家进入抽奖群参与抽奖,大家肯定都可以参与的。
我的小碗汤
2018/08/22
9360
【插件】解放鼠标,让浏览器更智能
Wetab新标签页:内置实用小组件的浏览器扩展,重新定义浏览器主页
除了社交媒体,浏览器可能是我们日常工作、学习和生活中最常用的平台之一。然而,在使用浏览器的过程中,我们经常被书签管理、标签管理等问题所困扰。例如,书签栏混乱不堪,无法快速查找到所需书签。
数字花园
2023/08/01
1.8K0
Wetab新标签页:内置实用小组件的浏览器扩展,重新定义浏览器主页
《最新出炉》系列入门篇-Python+Playwright自动化测试-10-标签页操作(tab)
标签操作其实也是基于浏览器上下文(BrowserContext)进行操作的,而且宏哥在之前的BrowserContext也有提到过,但是有的童鞋或者小伙伴还是不清楚怎么操作,或者思路有点模糊,因此今天单独来对其进行讲解和分享一下,希望您有所帮助。
北京-宏哥
2023/07/27
7821
《最新出炉》系列入门篇-Python+Playwright自动化测试-10-标签页操作(tab)
Chrome浏览器\Edge浏览器\安装扩展程序教程
找到下载的文件点击 下载可疑文件,(说明:这里并非可疑文件,而是 Google 为了垄断,从第三方商店(比如Crx搜搜)安装的默认会被 Chrome 阻止下载)
小焱
2025/06/10
7220
Chrome浏览器\Edge浏览器\安装扩展程序教程
京东一面:浏览器跨标签页通信的方式都有什么?
没错,还是京东一面的问题,首先问的是浏览器跨标签也通信的方式有什么,我答完浏览器通信通信的方式,后面就接着问 JavaScript 有什么方式的了。
winty
2024/04/15
2690
京东一面:浏览器跨标签页通信的方式都有什么?
【花雕学AI】32:WeTab——使用 ChatGPT 聊天的新标签页,免费又好用
你是否厌倦了每次打开浏览器都看到同样的新标签页?你是否想要让你的新标签页更有个性,更有趣,更有用?如果是的话,那么你一定要试试 WeTab!
驴友花雕
2023/05/08
1K0
【花雕学AI】32:WeTab——使用 ChatGPT 聊天的新标签页,免费又好用
进一步防止 Selenium 被检测——如何防止浏览器用新标签页打开链接?
在文章:(最新版)如何正确移除Selenium中的 window.navigator.webdriver中,我们讲到了Page.addScriptToEvaluateOnNewDocument这个方法,它可以让当前标签页打开的所有网页,在网页内容加载之前执行一段 JavaScript 代码,从而防止网站检测到window.navigator.webdriver属性。
青南
2020/04/28
4.6K0
优质工具推荐(资料网站、浏览器插件、Mac 软件等)
本文列举一些自己工作、学习中用到的比较推荐的资料网站、浏览器插件和 Mac 软件等,希望对大家有帮助。
明明如月学长
2021/09/08
7350
HandsomeTab - 优雅的新标签页扩展
HandsomeTab 是一个简洁优雅的浏览器新标签页扩展,让你的浏览器更加美观实用。
HandsomeYo
2025/04/03
940
美化神器chrome新标签页—Infinity新标签页
Chrome新标签页是指在打开谷歌浏览器的时候,如果没有设置主页而显示的默认界面,或者用户点击Chrome的标签按钮产生的一个新的浏览器初始界面,在该界面中用户可以重新打开一个新的网址或者操作一些Chrome应用,如果没有安装任何Chrome插件的话,该页面显示的就是Chrome提供的默认新标签页,当然用户也可以选择在Chrome商店中搜索一款更加实用的新标签页插件来获得更加实用、个性化的新标签页。
爱游博客
2019/08/08
2.4K0
分享几个 AutoHotKey 脚本:一键切换IDEA多行标签页等
AutoHotKey 之于 Windows,就好比 Javascript 之于 Chrome, 千万不要错过“DIY”操作系统的乐趣!
CRMEB商城源码
2022/07/26
2K0
Edge 的“睡眠标签页”
打开 Edge 的时候发现左上角一个弹窗显示说什么现在超过2小时未使用的标签页会进入“睡眠状态”以节省系统资源(内存),当时看到就觉得这个挺有意思的,这个新功能支持休眠时间与站点是否休眠设置,在浏览器 url 栏输入 edge://settings/system 即可进入设置页面
2Broear
2024/03/12
2620
Edge 的“睡眠标签页”
《最新出炉》系列入门篇-Python+Playwright自动化测试-15-playwright处理浏览器多窗口切换
浏览器多窗口的切换问题相比大家不会陌生吧,之前宏哥在java+selenium系列文章中就有介绍过。大致步骤就是:使用selenium进行浏览器的多个窗口切换测试,如果我们打开了多个网页,进行网页切换时,我们需要先获取各个页面的句柄,通过句柄来区分各个页面,然后使用switch_to.window()实现切换,这样的操作比较麻烦,而且宏哥在介绍和讲解的时候,也写了好几篇相关的文章。反过来今天我们所学的playwright来处理浏览器多窗口切换却比selenium更为简单快捷。下边宏哥就给小伙伴们或者童鞋们介绍一下playwrigh如何处理浏览器多个窗口的切换方法。
北京-宏哥
2023/09/01
1.2K1
《最新出炉》系列入门篇-Python+Playwright自动化测试-15-playwright处理浏览器多窗口切换
推荐几个火狐浏览器插件好_安卓火狐浏览器插件
目前,谷歌浏览器市场占有率最高,谷歌公司号称不作恶,实际上也作了一些恶,只不过底线比百度高一点。因为各类屏蔽广告的插件有损谷歌自己投放的广告的收益,因此谷歌对广告屏蔽插件下手了,削弱插件的屏蔽效果,以展现更多的广告。谷歌还通过在自家网站上提示不支持其它浏览器的手段,来打压其它浏览器。(由于CSDN现在基本不能发超链接了,下面这几篇文章我原本给了连接的,但现在不得不删掉,大家自己按标题搜索文章吧)
全栈程序员站长
2022/11/10
4.1K0
推荐几个火狐浏览器插件好_安卓火狐浏览器插件
软件测试/人工智能|Edge浏览器实用插件推荐
我们要把edge玩出花,让它充分发挥自己的强大实力,就需要安装各个功能强大的插件,这些插件可以帮助我们实现各种功能,本文就来给大家介绍一下几款实用的edge浏览器插件。
霍格沃兹测试开发Muller老师
2023/12/14
2720
推荐阅读
相关推荐
Google设置新标签页默认地址
更多 >
LV.0
测吧(北京)科技有限公司测试开发工程师
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验