欢迎访问我的网站与公众号!点击与扫码即可进入,谢谢关注!

放弃selenium了,容易被检测,每次测试得随着浏览器版本手动安装驱动,这里的Playwright是微软开源的web自动化测试工具
支持主流的浏览器,包含:Chrome、Firefox、Safari、Microsoft Edge 等,同时支持以无头模式、有头模式运行.
也支持很多语言,常用的python Node C++ Java都有支持,本人业余玩玩python
并提供了同步、异步的 API,可以结合 Pytest 测试框架 使用,并且支持浏览器端的自动化脚本录制。

直达——>playwright文档

安装

pip install playwright

安装驱动 playwright install chromium

  1. 按需安装,种类有chromium, chrome, chrome-beta, msedge, msedge-beta, msedge-dev, firefox, webkit
  2. 如果pyinstaller 打包报错 Please run the following command to download new browsers
    使用PLAYWRIGHT_BROWSERS_PATH=0 playwright install chromium

同步API

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
from playwright.sync_api import sync_playwright
# with管理器(方便使用,但是js加载如果有事件监听太多可能会崩溃)
with sync_playwright() as p:
# 可以选择chromium、firefox和webkit运行chrome浏览器
# False是有头模式,默认为true是无头模式
browser = p.chromium.launch(headless=False)
context = browser.new_context()
# 打开新页面
page = context.new_page()
# 调到指定页面
page.goto('https://www.baidu.com/') # 打开百度地址
# 标题
print(page.title())
page.fill('#kw', 'python') # 输入内容
page.click('#su') # 点击搜索
# 关闭
browser.close()

# 非with管理器,一般情况用with就可以了
p = sync_playwright().start()
browser = p.chromium.launch()
# ... 后面一样

基础用法

定位(支持xpath、css、文本等)

css

1
2
3
4
5
6
# 先定位再点击
element = page.locator('#su')
element.click()
# 直接点击
page.click('input[name="goto_tdouya_homepage"]')
page.click("#nav-bar .contact-us-item")

xpath

1
2
3
page.click('xpath=//*[@id="s-top-left"]/a[1]')
# 省略xpath
page.click('//*[@id="s-top-left"]/a[1]')

文本

1
2
3
4
5
6
7
8
9
# 第一个没有对新闻加引号,表示模糊匹配,对大小写不敏感
# 第二个对新闻加了引号,精确匹配,对大小写敏感
page.locator("text=新闻").click()
page.locator("text='新闻'").click()
page.locator(":text('Playwright')").click()
# 查找子代或后代包含对应文本
page.locator(':has_text("Playwright")').click()
# 相反has_not_text
page.locator(':has_not_text("Playwright")').click()

css+文本

1
2
page.locator('article:has_text("Playwright")').click()
page.locator('article:has'text=Playwright').click()

悬停

1
page.locator("//span[text()='设置']").hover()

获取内容

1
2
3
4
5
6
# 获取源码,可搭配beautifulsoup
html = page.content()
# 所有img节点,for循环一下获取单个的。。。详情可以看第二章例子
imgs = page.query_selector_all('img')
# 获取单个节点
ele1 = page.query_selector('#id.class')

获取属性

1
2
3
4
5
6
# 标签a的链接
a.get_attribute('href')
# 标签a的文本
a.inner_text()
# 输入框的值
input.input_value()

文本输入

1
2
3
page.goto('https://www.baidu.com/')  # 打开百度地址
page.fill('#kw', 'python') # 输入内容
page.click('#su') # 点击搜索

模拟人工输入

1
2
# delay 是设置输入延迟时间,眼不然看不到效果
page.get_by_placeholder('手机号或邮箱').type('1760123456',delay=1000)

等待

1
2
3
4
5
6
7
8
9
10
# 等待元素出现 超时5秒
page.wait_for_selector('#my-element', timeout=5000)
# visible:指定元素必须可见,默认为 False。
# hidden:指定元素必须隐藏,默认为 False。
page.wait_for_selector('#my-element', stat=5000)
# load:页面完全加载完成,默认。
# domcontentloaded:DOM 内容加载完成。
# networkidle0:网络空闲状态时。
# networkidle2:网络连接数稳定且超过 500 毫秒。
page.wait_for_load_state('networkidle')

截图

1
2
3
4
5
6
7
8
# page.screenshot(path=None, *, full_page=True, clip=None, quality=None, omit_background=False)
# path:指定截图保存的文件路径和文件名。
# full_page:指定截图是否包含整个页面,默认为 True。
# clip:指定截图的大小和位置。
# quality:指定截图的质量。
# omit_background:指定是否忽略背景色。
page.screenshot(path='example.png', full_page=True)
page.screenshot(clip={'x': 0, 'y': 0, 'width': 800, 'height': 600})

选择框

  1. 示例:
    1
    2
    3
    4
    5
    <select id="xz">
    <option value="bj">北京</option>
    <option value="sh">上海</option>
    <option value="sz">深圳</option>
    </select>
  2. 操作:
    1
    2
    3
    page.select_option('#xz', 'sh')          # 通过value选择
    page.select_option('#xz', '2') # 通过下标选择
    page.select_option('#xz', '上海') # 通过label选择

浏览器页面

切换页面

1
2
3
4
with context.expect_page() as new_page_info:
page.click('打开新链接')
new_page = new_page_info.value
new_page.wait_for_load_state()

关闭指定页面

1
2
3
4
5
6
# 点击淘宝按钮,获取所有页面list,如果页面标题是淘宝,就关闭
page.click('text=淘宝')
pages = context.pages
for p in pages:
if(p.title()=='淘宝'):
p.close()

上传文件

1
2
3
page.goto('https://deershare.com/send')  # 打开地址
# (定位元素, 本地文件路径)
page.set_input_files('input[type=file]', r'D:\test.txt')

获取保存的cookie直接登录

  1. 以一个测试平台为例:http://demo.liumatest.cn/#/home/dashboard
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    with sync_playwright() as p:
    browser = p.chromium.launch(headless=False, slow_mo=5000) # 设置了每步等待时间为5s
    context = browser.new_context()
    page = context.new_page() # 打开一个页面
    page.goto('http://demo.liumatest.cn/#/home/dashboard') # 打开地址
    # 输入账号密码登录
    page.fill('#username','demo') # 输入账号
    page.fill('#password','123456') # 输入密码
    page.click('#login') # 点击登录
    context.storage_state(path="cookie.json") # 保存storage_state 到JSON文件
    page.wait_for_timeout(2000)
    browser.close()
  2. 使用cookie登录
    1
    2
    3
    4
    5
    6
    7
    with sync_playwright() as p:
    browser = p.chromium.launch(headless=False, slow_mo=5000)
    context = browser.new_context(storage_state="cookie.json")
    page = context.new_page() # 打开一个页面
    page.goto('http://demo.liumatest.cn/#/home/dashboard')
    page.screenshot(path="image.png")
    browser.close()

异步API

1
2
3
4
5
6
7
8
9
10
import asyncio
from playwright import async_playwright
async def main():
async with async_playwright() as p:
browser = await p.chromium.launch(headless=False)
page = await browser.newPage()
await page.goto('https://www.baidu.com/')
await page.screenshot(path='example-2.png')
await browser.close()
asyncio.get_event_loop().run_until_complete(main())

模拟手机模式

1
2
3
4
5
6
7
8
9
10
from playwright import sync_playwright
with sync_playwright() as p:
iphone_11 = p.devices['iPhone 11 Pro']
browser = p.chromium.launch(headless=False)
context = browser.newContext(**iphone_11, locale='zh-CN')
page = context.newPage()
page.goto('https://www.baidu.com/')
page.click('#logo')
page.screenshot(path='colosseum-iphone.png')
browser.close()

浏览器中运行JS

1
2
3
4
5
6
7
8
9
10
11
12
13
14
from playwright import sync_playwright
with sync_playwright() as p:
browser = p.chromium.launch(headless=False, slowMo=1000)
page = browser.newPage()
page.goto('https://www.baidu.com/')
dimensions = page.evaluate('''() => {
return {
width: document.documentElement.clientWidth,
height: document.documentElement.clientHeight,
deviceScaleFactor: window.devicePixelRatio
}
}''')
print(dimensions)
browser.close()

录制脚本

  1. 命令行键入 –help 看到所有可后接选项
    1
    2
    playwright codegen --help
    playwright codegen --help
  2. 从起始页为xingzheai.cn开始录制
    1
    playwright codegen https://xingzheai.cn/
  3. 打开xingzheai.cn,用Chromium驱动,将结果保存为my.py的python文件,可以打开这个文件重现
    1
    2
    3
    4
    playwright codegen --target python -o 'my.py' -b chromium https://xingzheai.cn/
    -target:规定生成脚本的语言,有JS和Python两种,默认为Python
    -b:指定浏览器驱动
    -o:将录制的脚本保存到一个文件