目录
一、简介+使用场景
二、环境部署(准备)
三、代码生成器(优势)
四、元素定位器(核心)
五、追踪查看器(辅助)
六、权限控制与认证(高级)
七、其他重要功能(进阶)
coding-real mind writing-genuine heart
作者:Maker陈 本文字数:4.5k 阅读时长≈1分钟
Playwright是什么?来自ChatGPT回答:
Playwright是跨语言支持的,支持Python、Java、Node.js、.NET
使用场景:
Playwright环境部署简单,不像Selenium那样需要下载浏览器对应版本的驱动程序chromedriver,直接安装即可:
安装所需的浏览器:
这个命令会安装所有playwright支持的浏览器,包括Chrome、Firefox、WebKit,如下图:
如何只安装特定的浏览器,比如Chrome:
playwright install chromium
Chrome和Chromium有什么关系?
可看做同一个项目下的两个分支,chromium是测试开源版,所有的功能都会先在其身上测试,确定稳定运行后再移植到chrome上,而chrome是Google正式商业版浏览器,两者由Google官方和chromium社区进行维护
由于系统问题安装失败时怎么办?
看一下各种浏览器在Windows、Linux、MacOS下的默认安装路径:
以安装Chrome浏览器来说,两种解决途径:
https://playwright./builds/chromium/1080/chromium-win64.zip
from playwright.sync_api import sync_playwright
browser = sync_playwright().start().chromium.launch(executable_path='C:\Users\lenovo\AppData\Local\ms-playwright\chromium_win64_special-1050\chrome-win\chrome.exe')
playwright能够按顺序自动生成用户与浏览器交互行为(包括鼠标点击、键盘输入、元素拖动、页面跳转、窗口切换等)的自动化代码,使用命令行输入,其后跟要访问的url:
playwright codegen https://v
你可以在浏览器页面进行各种交互行为,生成器会按顺序自动生成代码:
代码生成后可以直接复制在你的IDE中,节省了大量时间,提高爬虫或自动化效率
playwright支持的网页元素定位器有很多:
官方推荐的定位方式,这种定位方式与代码生成器中的元素定位是一样的
from playwright.sync_api import sync_playwright
def run() -> None:
browser = sync_playwright().start().chromium.launch(headless=False, slow_mo=60)
context = browser.new_context()
page = context.new_page()
page.goto(url)
page.get_by_text("登錄").click()
page.get_by_placeholder("Please enter your email").click()
page.get_by_placeholder("Please enter your email").fill('123')
context.close()
browser.close()
sync_playwright().stop()
run()
语法非常简洁,这种page.get_by_text("登錄").click()元素定位方式就是官方推荐的方式,这种定位方式是唯一的,不像CSS/XPath定位,一旦网页DOM元素改变,定位也要跟着变,所以官方才推荐这种元素唯一的定位方式
page.locator('css=<元素定位器>')
page.locator('xpath=<元素定位器>')
CSS定位和XPath定位方法是一样的,可以去掉前面的"css="或"xpath="前缀,playwright会自动解析里面的定位器是那种方式:
page.locator('<CSS/XPath元素定位器>')
获取网页源码:
playwright虽然支持对Python的同步和异步操作,但底层是由异步实现的,有时候为了避免操作速度过快可能会进行一些延时操作,这里不使用下面这种延时操作:
import time
# 延时2秒,以秒为单位
time.sleep(2)
而是使用playwright官方内置的延时操作:
# 延时2秒,这里是以毫秒为单位
page.wait_for_timeout(2000)
创建追踪器
追踪的目的是为了看使用playwright与浏览器交互时发生了什么?方便我们更加深刻的理解内部操作逻辑,示例代码如下:
from playwright.sync_api import sync_playwright, Playwright
def run(playwright: Playwright) -> None:
browser = playwright.chromium.launch(headless=False)
context = browser.new_context()
context.tracing.start(snapshots=True, screenshots=True, sources=True)
page = context.new_page()
page.goto('https://v')
page.screenshot(path='screenshot_test.jpg')
context.tracing.stop(path='playwright_trace.zip')
context.close()
browser.close()
with sync_playwright() as playwright:
run(playwright)
这个示例代码是为了查看导航到playwright官网并进行截图操作时发生了什么?
注意,创建追踪器是在context对象进行操作,在context创建之后,关闭之前
其中的操作行为很简单,只是导航到了playwright官网进行了一个截图动作,并设置保存的文件名及格式,结束后会在目录生成jpg图片和追踪器的ZIP压缩文件
查看追踪器 -- 两种方式
操作如下:
playwright show-trace playwright_trace.zip
无论那种方式,你将看到如下图的追踪器结构:
正如上图所示,示例代码只进行了三个动作,即打开一个空白页面,然后导航到playwright官网,最后进行截图,每个动作都包含了执行时间
在其下面有一些属性,其中network功能类似于开发工具中的抓包请求,还有日志、定位器、源码、控制台等属性功能
使用场景:当爬虫工程师抓取数据或自动化工程师测试某些重要功能时需要注册/登录之后,才能看见我们想要抓取或测试的内容
如果验证过程过于复杂或麻烦,比如滑动验证码如何识别缺口位置及拖动
对于点触验证码来说,又有按顺序点击不同长度的文字,比如bilibili,按文字说明点击符合要求的图片,比如请点击下方含有小轿车的图片,链接如下:
还有行为验证码,比如给你一组图片,让你转动图片直到与给定示例图片相同的方向才行,Twitter其中一种验证方式就是这样的
国外有些网站的注册/登录验证有可能还需进行邮箱验证码二次验证,国内的验证码大多二次验证以短信为主
当然,其实我们也可以使用OpenCV、深度学习、第三方打码服务平台(付费)、手机短信验证码的自动化处理(监听手机短信内容+将短信内容转发到指定的位置)来解决
但是如果你临时接到一个需求并且时间比较急,破解验证过程又比较复杂麻烦的话可采用手动验证获取其中的登录凭证以json文件保存到本地,这个文件里面保存的其实就是相关的cookie和账户的一些信息,有两种方式可以获取到:
playwright codegen https:// --save-storage=auth.json
后面的auth.json就是说我们要把相关权限保存到当前目录的auth.json文件里面
比如我们要获取polygonscan的地址和标签数据,网址如下:
https:///accounts/label/aave
在没有登录前数据是不会显示全的,如下图所示:
用playwright手动获取凭证保存到auth.json,看一看登录过程
文件auth.json保存成功:
打开看看里面的内容:
可以清晰的看到,auth.json里面的内容其实就是cookies的相关信息,每个cookie字段都以字典的格式存储起来
测试该auth.json里面的cookies是否有效:
playwright codegen --load-storage=auth.json https:///accounts/label/aave
再次打开不需要验证:
测试成功,该auth.json文件里面的cookies是有效的,账户早已存在并且数据显示是全的,非常Nice!
from playwright.sync_api import sync_playwright
def run():
playwright = sync_playwright().start()
browser = playwright.chromium.launch(headless=False, slow_mo=100, args=['--disable-infobars', '--window-size=1366,880'])
context = browser.new_context()
page = context.new_page()
page.set_viewport_size({'width': 1366, 'height': 880})
page.goto('https:///accounts/label/aave')
page.get_by_role('button', name='Close').click()
#把凭证权限保存到当前目录的auth.json文件
context.storage_state(path='auth.json')
#延时3分钟以保证足够的时间完成手动登录
page.wait_for_timeout(3*60*1000)
context.close()
browser.close()
playwright.stop()
run()
操作方式和生成器命令行方式是一样的,会自动打开chrome浏览器,然后需要我们手动进行登录验证
如何导入auth.json进行自动化数据抓取或测试:
from playwright.sync_api import sync_playwright
def run():
playwright = sync_playwright().start()
browser = playwright.chromium.launch(headless=False, slow_mo=100, args=['--disable-infobars', '--window-size=1366,880'])
"""
Generate authentication by using codegen:
> playwright codegen https:// --save-storage=auth.json
Verifing the authentication whether is alive or useful:
> playwright codegen --load-storage=auth.json https:///accounts/label/aave
"""
context = browser.new_context(storage_state='auth.json')
page = context.new_page()
page.set_viewport_size({'width': 1366, 'height': 880})
page.goto('https:///accounts/label/aave')
# 获取网页源码,方便进行元素解析及数据获取
response = page.content()
# banabala-----------------------
# 延迟2秒-----------------------
page.wait_for_timeout(2*1000)
context.close()
browser.close()
playwright.stop()
run()
我们也可以使用第三方解析库BeautifulSoup、PyQuery、XPath等对网页源码中的数据进行解析,有时候可能会更加方便,比如使用PyQuery
from pyquery import PyQuery as pq
doc = pq(page.content())
这一小节很重要,爬虫工程师或自动化测试工程师进阶必备,需重点掌握
爬虫逆向时,我们一般需要模拟JS环境来执行加密代码,从而获得最终的加密结果
但是如果我们能够模拟浏览器环境,自动执行JS加密代码,这样是不是就能比较轻松的完成逆向过程呢?
而playwright能够打开浏览器进而模拟,JS加密代码是从目标远程服务器传到本地客户端执行的
所以只要我们能够找到执行加密逻辑的JS文件,定位其中的加密函数或属性,把它挂载到全局的window对象再获取,不就很容易获得加密结果了吗?
我们先来看一个简单的playwright是如何执行JS代码的示例:
page.evaluate('array => array.length', list(range(10)))
调用page对象的evaluate函数能够执行JS代码,array指代的是后面的列表
当然目前我们是不能修改远程的JS文件的,除非寻找漏洞,利用黑客手段
现在我们要做的是在远程服务器将JS代码传到本地浏览器客户端时,用已经修改好的JS文件(增加了一些内容,比如将加密函数挂载到window对象)替换浏览器对应的JS文件,让浏览器执行这个替换好的JS文件,从而获得加密结果:
来看看本地的JS文件是怎样override浏览器JS文件的:
page = browser.new_page()
page.route(
"/static/js/chunk.js",
lambda route: route.fulfill(path="./chunk.js")
)
page.goto(url)
page.evaluate('''function crypto() {return window.encryParams("%s")}''' % params)
调用page对象的route函数,传入浏览器JS文件和本地JS文件的路径,然后我们把本地JS文件中的加密函数挂载到全局window对象的encryParams属性上
这时encryParams也就等同于这个加密函数,然后在传入参数让它自动进行加密,最后调用evaluate函数执行我们构造的JS函数就能获取加密结果
注意:本地JS文件内容是我们从浏览器的JS加密文件全部复制下来的,只不过增加了一些东西
设备仿真
这个功能可能自动化测试工程师会用到,比如要测试博客园网站在iPhone 13设备上是否兼容:
from playwright.sync_api import sync_playwright
def run():
playwright = sync_playwright().start()
browser = playwright.chromium.launch(headless=False, slow_mo=5)
iphone_13 = vices['iPhone 13']
context = browser.new_context(**iphone_13, locale='de-DE', timezone_id='Europe/Berlin',
permissions=['notifications', 'geolocation']
page = context.new_page()
page.goto('https://cnblogs.com/makerchen')
page.wait_for_timeout(20000)
context.close()
browser.close()
playwright.stop()
run()
看一看仿真效果:
监听和修改网络
playwright能够追踪、修改某个页面的所有请求,包括document、XHR和fetch请求等
比如我们要修改document请求源码中的<title>标签内容,可以这样做:
from playwright.sync_api import Route
def handle_route_response(route: Route) -> None:
# Fetch original response.
response = route.fetch()
# Add a prefix to the title.
body = response.text()
body = body.replace("<title>", "<title>My prefix:")
route.fulfill(
# Pass all fields from the response.
response=response,
# Override response body.
body=body,
# Force content type to be html.
headers={**response.headers}
)
Playwright官网: