0704Playwright
Playwright(p257)是微软开源的自动化测试工具(官方文档),它的api设计接近 pypeteer(综合起来Playwright>Pypeteer>Selenium)。
Playwright特点:
- 支持主流的浏览器。基于chromium(Chrome、Edge)、FireFox、Safari(基于Webkit)
- 支持移动端页面测试
- 安装和配置简单,无需安装额外的WebDriver(跟Pypeteer无非就是它帮你安装好依赖的东西)
- Playwright 提供和自动等待相关的 API,在页面加载时会自动等待对应的节点加载,大大减小了 API编写的复杂度。
- 自动代码生成
安装
pip3 install playwright [chromium|FireFox|wekit]
- 下载必要的浏览器(好家伙把主流的浏览器[chromium、FireFox、wekit]都下载下来了)和配置对应驱动、环境变量:
playwright install
- 安装到目录:
/Users/xx/Library/Caches/ms-playwright/
- 安装到目录:
使用
典型的例子
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
#同步版本
from playwright.sync_api import sync_playwright
with sync_playwright() as playwright:
browser = playwright.chromium.launch(headless=False)#这里跟Pypeteer的launch差不多
context = browser.new_context()
page = context.new_page() #也可以用browser.new_page()
page.goto("https://cn.bing.com/")
label=page.locator("#sb_form_q") #查找id=sb_form_q,输入python,回车
label.fill("python")
label.press("Enter")
time.sleep(20)
page.close()
context.close()
#异步版本
import asyncio
from playwright.async_api import async_playwright
async def main() -> None:
async with async_playwright() as playwright:
browser = await playwright.chromium.launch(headless=False)
context = await browser.new_context()
page = await context.new_page()
await page.goto("https://cn.bing.com/")
await page.fill('#sb_form_q','python') #晕 page.locator 没有异步版本函数
await page.press('#sb_form_q','Enter')
await asyncio.sleep(20)
await page.close()
await context.close()
await browser.close()
asyncio.run(main())
launch的参数。
launch传入的参数跟Pypeteer,命名有些差异
参数名称 | 参数类型 | 参数说明 |
---|---|---|
executable_path | str | 可执行文件的路径。实际就是指定chromium浏览器路径(也可以指定Chrome路径) |
env | Dict[str, str|float|bool]|环境变量,可以传人字典形式的数据 | |
headless | bool | 是否以”无头”的模式运行 . 默认为 true |
slow_mo | float | 操作减速,单位是毫秒。减缓Pyppeteer的一些模拟操作 |
args | Sequence[str] | 在执行过程中传入的额外参数.args=[’–disable-infobars’,#禁用提示条 ‘–window-size=1366,768’#页面大小设置 ] |
ignore_default_args | bool | 是否忽略Pyppeteer的默认参数。如果使用这个参数,那么最好通过 args 设置一些参数,否则可能会出现一些意想不到的问题。这个参数相对比较危险,慎用。 |
handle_sigint | bool | 是否响应 SIGINT 信号,也就是是否可以使用 Ctrl+C终止测览器程序默认是 True |
handle_sigterm | bool | 是否响应 SIGTERM 信号(一般是 ki11 命令),默认是 True |
handle_sighup | bool | 是否响应 SIGHUP信号,即挂起信号,例如终端退出操作,默认是True。 |
timeout | float | 等待浏览器实例启动的最 超时(以毫秒为单位)。默认值为 30000 |
devtools | bool | 是否自动为每一个页面开启调试工具,默认是 false。如果将这个参数设置参数就会无效,会被强制设置为 false为 True 那么 headless |
proxy | ProxySettings | |
downloads_path | str | Path |
CSS选择器(Playwright对CSS选择器又做了扩展!!!!)
扩展 | 作用 | 例子 |
---|---|---|
text=str text(str) | 文本选择器 | page.click(“text=Log in”)#匹配 文本=Log in page.click(“#nav-bar:text(‘Contact us’)”)#匹配 id=na-bar节点文本值=Contact us |
has-text(str) | 包含文本(Playwright的constains) | page.click(“article:has-text(‘Playwright’)”)#匹配 article节点文本值包含Playwright |
has() | page.click(“article:has(‘div.promo’)”) #返回<article>内部具有 <div class=’promo’> 的元素 |
XPath(带前缀xpath=
):
page.click('xpath=button')
模拟成移动浏览器
1
2
3
iPhone= playwright.devices['iPhone 12 Pro Max']
browser = await playwright.chromium.launch(headless=False)
context = await browser.new_context(**iPhone,locale='zh-CN')
自动代码生成
- 查看命令:
playwright codegen --help
- 执行代码生成会打开浏览器和
playwright inspector
(实时显示代码生成) - 主要的参数
--target
:生成语言。python、python-async(异步执行)-b
:浏览器(chromium、webkit、firforx)- 例子:
playwright codegen --target=python-async -o script3.py https://www.bing.com
其他函数
- 1.page的其他函数/属性
函数 | 功能 | 例子 |
---|---|---|
goto | until参数:<> “domcontentloaded”:在触发“domcontentloaded”事件时完成操作。 “load”:触发 load事件时完成操作。 “networkidle”:当500毫秒内没有新的网络请求时触发,认为操作已完成。 “commit”:考虑在接收到网络响应并且文档开始加载时完成操作。 proxy: {“server”: “host:port”, “username”: “user”, “password”: “pwd”} | |
locator | 定位到指定节点 | |
click | 点击 | page.click(“#nav-bar:text(‘Contact us’)”) |
fill | 输入字符串 | page.fill(‘#sb_form_q’,’python’) |
type | 在指定的元素中输入文本内容 | page.type(‘#sb_form_q’, ‘python’, delay=100) |
press | page.press(‘#sb_form_q’,’Enter’) | |
evaluate | 执行js code | await page.evaluate(‘window.scrollBy(0, document.body.scrollHeight)’)# 滚动到页面底部 |
eval_on_selector eval_on_selector_all | 在单个/所有符合选择器的节点执行js 等效于Pypeteer | |
on | 事件监听(和Pypeteer | |
route | 路由处理 | page.route(re.compile(“.(png)|(jpe{0,1}g)”), lambda route,request:route.abort())#不处理图片请求 page.route(‘/’, lambda route,request:route.fulfill(path=”./my_response.html”)) #替换请求页面 |
add_init_script | page.add_init_script(‘Object.defineProperty(navigator, “webdriver”, {get: () => undefined})’)#反爬虫检测 | |
query_selector query_selector_all | 获取单/多个,未找到返回None | element=page.query_selector(‘a.name’) elements=page.query_selector_all(‘a.name’) |
get_attribute | 获取节点属性 | href=page.get_attribute(‘a.name’, “href’) |
wait_for_event | wait_*类函数可能抛异常 | |
wait_for_load_state | 等待页面的加载状态 | state参数:(goto的util参数) page.goto(‘https://cn.bing.com’) page.wait_for_load_state(‘networkidle0’)# 等待网络空闲状态 |
wait_for_function | 该方法会持续执行指定的 JavaScript 函数,直到函数返回 True。它可以用于等待页面上动态变化的内容出现,或者等待异步操作完成。 | page.wait_for_function(‘()=>document.querySelector(“#myButton”).disabled===false’) |
wait_for_selector | 等待与指定 CSS 选择器匹配的元素出现在页面中 | page.wait_for_selector(‘#myButton’) page.wait_for_selector(‘.my-div’, visible=True) # 等待可见的元素 |
wait_for_timeout | 等待调用方法时等待的时间(相当于sleep) | |
wait_for_url | 等待主框架导航到给定的URL | await page.click(“a.delayed-navigation”) await page.wait_for_url(“**/target.html”) |
expect_navigation | 等待页面完成导航 | # 点击搜索按钮 with page.expect navigation():page.click(“text-百度一下”) |
expect_event | ||
expect_popup | ||
expect_worker | ||
expect_request | ||
expect_request_finished | ||
screenshot | 截图 | |
conent | 获取html源码 | |
keyboard | kb=page.keyboard kb.type(‘Hello World!’) #删除掉 World kb.press(‘ArrowLeft’) kb.down(‘Shift’) for i in rang(len(‘ World’)):kb.press(‘ArrowLeft’) kb.up(‘Shift’) kb.press(‘Backspace’)#按回车 | |
mouse | 鼠标 | page.mouse.click(x,y,button,click_count,delay) page.mouse.wheel(delta_x, delta_y) page.mouse.move(0, 0)#移动到[0,0]坐标 page.mouse.down() page.mouse.up() |
- 2.节点函数/属性
函数 | 功能 | 例子 |
---|---|---|
text_content | 获取文本 | page.query_selector(“h2”).text_content() |
get_attribute | 获取节点属性 | page.query_selector(‘img.cover’).get_attribute(‘src’) |
- 3.Locator函数
函数 | 功能 | 例子 |
---|---|---|
count | 返回匹配数量 | count()==0则没有匹配的节点 |
click | 执行点击 | loc.click(click_count=5,delay=100) |
press | 输入内容 | loc.press(‘Enter’) |
type | 输入文本内容 | loc.type( ‘python’, delay=100) |
drag_to | 拖到 | |
all | 返回所有匹配元素到list | |
get_attribute | 获取属性 | |
inner_html | ||
inner_text | ||
text_content | 节点文本 | |
scroll_into_view_if_needed | 滚动到view |
Q&A
- ` Execution context was destroyed, most likely because of a navigation`
检查代码是否在跳转了新页面后又在使用
query_selector
之类的函数。比如用迭代器(yield,惰性求值导致页面跳转后还去执行前一个页面的操作)存储了所有页面,处理完当前的页面再for取出下一个页面
This post is licensed under CC BY 4.0 by the author.