👍👍 快速上手 - 白月黑羽
快速上手
安装
原理
可以先安装第三方库
# 使用清华大学源
pip install requests -i https://pypi.tuna.tsinghua.edu.cn/simple
# 如果你在公司使用代理上网,pip安装可能出现SSL证书校验错误,可以加上信任参数 --trusted-host ,如下所示
pip install requests -i https://pypi.tuna.tsinghua.edu.cn/simple --trusted-host pypi.tuna.tsinghua.edu.cn
pip install playwright
playwright install chromium
quick start
from playwright.sync_api import sync_playwright
# 启动 playwright driver 进程
p = sync_playwright().start()
# 启动浏览器,返回 Browser 类型对象
browser = p.chromium.launch(headless=False, executable_path='C:\Program Files (x86)\Microsoft\Edge\Application\msedge.exe')
# 创建新页面,返回 Page 类型对象
page = browser.new_page()
page.goto("https://www.byhy.net/cdn2/files/selenium/stock1.html")
print(page.title()) # 打印网页标题栏
# 输入通讯,点击查询。这是定位与操作,是自动化重点,后文详细讲解
page.locator('#kw').fill('通讯') # 输入通讯
page.locator('#go').click() # 点击查询
page.wait_for_timeout(2000)
# 打印所有搜索内容
lcs = page.locator(".result-item").all()
for lc in lcs:
print(lc.inner_text())
input('close....')
# 关闭浏览器
browser.close()
input('4....')
# 关闭 playwright driver 进程
p.stop()
如果是自定义浏览器路径
browser = p.chromium.launch(headless=False, executable_path='C:\Program Files (x86)\Microsoft\Edge\Application\msedge.exe')
with的一种写发
from playwright.sync_api import sync_playwright
with sync_playwright() as p:
browser = p.chromium.launch(headless=False)
page = browser.new_page()
page.goto('https://www.byhy.net/cdn2/files/selenium/stock1.html')
print(page.title())
page.locator('#kw').fill('通讯\n')
page.locator('#go').click()
page.wait_for_timeout(2000)
# 打印所有搜索内容
lcs = page.locator(".result-item").all()
for lc in lcs:
print(lc.inner_text())
input('close...')
browser.close()
自动化编程
在CMD中执行
# 可能需要全路径
playwright.exe codegen
接下来所有的操作都会被控制台记录下来,如下:
import re
from playwright.sync_api import Playwright, sync_playwright, expect
def run(playwright: Playwright) -> None:
browser = playwright.chromium.launch(headless=False)
context = browser.new_context()
page = context.new_page()
page.goto("https://www.byhy.net/cdn2/files/selenium/stock1.html")
page.get_by_role("textbox", name="股票名称").click()
page.get_by_role("textbox", name="股票名称").fill("通讯")
page.get_by_role("button", name="查询").click()
# ---------------------
context.close()
browser.close()
with sync_playwright() as playwright:
run(playwright)
跟踪功能
代码示例如下:
from playwright.sync_api import sync_playwright
p = sync_playwright().start()
browser = p.chromium.launch(headless=False)
# 创建 BrowserContext对象
context = browser.new_context()
# 启动跟踪功能
context.tracing.start(snapshots=True, sources=True, screenshots=True)
page = context.new_page()
page.goto("https://www.byhy.net/cdn2/files/selenium/stock1.html")
# 搜索名称中包含 通讯 的股票
page.locator('#kw').fill('通讯')
page.locator('#go').click()
page.wait_for_timeout(1000) # 等待1秒
lcs = page.locator(".result-item").all()
for lc in lcs:
print(lc.inner_text())
# 搜索名称中包含 软件 的股票
page.locator('#kw').fill('软件')
page.locator('#go').click()
page.wait_for_timeout(1000) # 等待1秒
lcs = page.locator(".result-item").all()
for lc in lcs:
print(lc.inner_text())
# 结束跟踪
context.tracing.stop(path="trace.zip")
browser.close()
p.stop()
核心api(打开快照):
context.tracing.start(snapshots=True, sources=True, screenshots=True)
执行代码后,会发现同级目录下存在 trace.zip
文件,查看该文件有2中方法:
-
执行命令
playwright show-trace trace.zip
元素的定位
CSS选择器
# 根据id定位
page.locator('#kw')
# 根据class定位
page.locator(".result-item")
注意:如果一个标签有多个属性,那么只能选择一个
<span class="chinese student">张三</span>
指定任意 class
属性
page.locator('.chinese')
## 或者
page.locator('.student')
## 或者
page.locator('.chinese.student')
## 不能这样写
page.locator('.chinese student')
元素的验证
和 xpath
的验证一样
匹配多个元素
如果存在多个元素需要进行选择
from playwright.sync_api import sync_playwright
p = sync_playwright().start()
browser = p.chromium.launch(headless=False)
context = browser.new_context()
page = context.new_page()
page.goto('https://www.byhy.net/cdn2/files/selenium/sample1.html')
lct = page.locator('.animal')
print('第一个', lct.first.inner_text())
print('第二个', lct.nth(1).inner_text())
print('最后一个', lct.last.inner_text())
input('即将关闭浏览器...')
browser.close()
p.stop()
Locator 内部定位
from playwright.sync_api import sync_playwright
with sync_playwright() as p:
browser = p.chromium.launch(headless=False)
context = browser.new_context()
page = context.new_page()
page.goto('https://www.byhy.net/cdn2/files/selenium/sample1.html')
# 定位到bottom
lct = page.locator('#bottom')
print(lct.locator('span').all_inner_texts())
input('浏览器即将退出...')
page.close()
控制台效果
PS E:\code\ecoding_test\20250608_playwright> & C:/Python/Python313/python.exe e:/code/ecoding_test/20250608_playwright/3_元素定位_匹配内部元素.py
['版权', '发布日期:2018-03-03', '备案号 苏ICP备88885574号']
浏览器即将退出...
可以看到存到了数组中
子元素和后代元素
# 子元素
#bottom > div.footer2 > span
# 后代元素(中间可能隔了一些元素)
#bottom span
比如刚才的代码的改造
lct = page.locator('#bottom')
print(lct.locator('span').all_inner_texts())
## 可以改造成
lct = page.locator('#bottom span')
print(lct.all_inner_texts())
缺省等待时间
playwright 会默认等待 30s,也可以自行定义
print(element.inner_text(timeout=10000))
如果响整体修改缺省时间
from playwright.sync_api import sync_playwright
with sync_playwright() as p:
browser = p.chromium.launch(headless=False)
context = browser.new_context()
# 整体设置等待缺省时间 10s
context.set_default_timeout(10000)
page = context.new_page()
page.goto('https://www.baidu.com')
page.locator('#kw').fill('python')
page.click('#su')
input('浏览器即将关闭...')
browser.close()
界面操作
元素通用操作
获取隐藏文本
lct = page.locator('#source')
lct.inner_text() # 获取文本内容(不包括隐藏的内容)
lct.text_context() #获取文本内容(包括隐藏的内容)
获取属性
lct = page.locator('#source')
lct.get_attribute('href') # 获取属性
获取元素内部 Html
lct = page.locator('#source')
lct.inner_html() # 获取内部 html
点击
lct = page.locator('#source')
lct.click() # 单击
lct.dbclick() # 双击
lct.hover() # 悬停
等待
page.locator('#dynamic').wait_for()
# 然后抓取
lc = page.locator('#dynamic + div')
print(lc.inner_text())
判断元素是否可见
page.locator('#source').is_visible()
## 注意:is_visible 不会等待,立刻返回界面是否存在该元素,wait_for 会等待时间
输入框操作
输入&清空
page.locator('#text').clear()
page.locator('#text').fill('xxx')
获取输入框里面的文字
page.locator('#text').input_value()
文件输入框
# 定位
lc = page.locator('input[type=file]')
# 单选一个文件
lc.set_input_files('d:/1.png')
# 或者 多选 文件
lc.set_input_files(['d:/1.png', 'd:/2.jpg'])
radio,如下面的 html:
<div id="s_radio">
<input type="radio" name="teacher" value="小江老师">小江老师<br>
<input type="radio" name="teacher" value="小雷老师">小雷老师<br>
<input type="radio" name="teacher" value="小凯老师" checked="checked">小凯老师
</div>
# 先打印所有老师的名字
lcs = page.locator('#s_radio input[name="teacher"]:checked').all()
teachers = [lc.get_attribute('value') for lc in lcs]
print('当前选中的是:', ' '.join(teachers))
# 确保点选 小雷老师
page.locator('#s_radio input[value="小雷老师"]').check()
# 取消选择
page.locator('#s_radio input[value="小雷老师"]').uncheck()
# 判断是否选中
page.locator('#s_radio input[value="小雷老师"]').is_checked()
checkbox,同 radio 一样
select单选框
不管原来选的是什么,直接使用 select
方法选择即可
page.locator('#ss_single').select_option('小江老师')
# 这里 select_option 参数是 选项 option 元素 的 value 或者 选项文本,要完全匹配
也可以使用关键字参数 index
, value
, label
指定分别根据 索引,value
属性, 选项文本 进行匹配,如:
# 根据 索引 选择, 从0 开始, 但是为0的时候,好像有bug
page.locator('#ss_single').select_option(index=1)
# 根据 value属性 选择
page.locator('#ss_single').select_option(value='小江老师')
# 根据 选项文本 选择
page.locator('#ss_single').select_option(label='小江老师')
# 清空所有选择
page.locator('#ss_single').select_option([])
select多选框
# 根据 value属性 或者 选项文本 多选
page.locator('#ss_multi').select_option(['小江老师', '小雷老师'])
# 根据 value属性 多选
page.locator('#ss_multi').select_option(value=['小江老师', '小雷老师'])
# 根据 选项文本 多选
page.locator('#ss_multi').select_option(label=['小江老师', '小雷老师'])
# 清空所有选择
page.locator('#ss_multi').select_option([])
获取select选中选项
page.locator('#ss_multi').select_option(['小江老师','小雷老师'])
lcs = page.locator('#ss_multi option:checked').all_inner_texts()
print(lcs)
网页操作
要 打开网址/刷新/前进/后退
, 可以分别调用 Page 对象的 goto/reload/go_back/go_forward
方法
获取 title
,可以调用 page
对象的 title
方法
frame/tab 切换等技巧
iframe 切换
# 产生一个 FrameLocator 对象
frame = page.frame_locator("iframe[src='sample1.html']")
# 再 在其内部进行定位
lcs = frame.locator('.plant').all()
for lc in lcs:
print(lc.inner_text(timeout=1000))
对比 selenium,playwright无需嵌套进入,直接一键进入
窗口切换
窗口切换
from playwright.sync_api import sync_playwright
with sync_playwright() as p:
browser = p.chromium.launch(headless=False)
context = browser.new_context()
# 整体设置等待缺省时间 10s
context.set_default_timeout(10000)
page = context.new_page()
page.goto('https://www.baidu.com')
page.locator('#kw').fill('python')
# 点击搜索
page.click('#su')
# 点击 第一个搜索标题
page.click('//h3[1]//a')
# 等2s
page.wait_for_timeout(2000)
# 新窗口的page
newPage = context.pages[1]
# 打印新窗口的窗口标题
print(newPage.title())
input('浏览器即将关闭...')
browser.close()
如果确定不了序号,那么就通过 title 来选择
for pg in context.pages:
# 得到该窗口的标题栏字符串,判断是不是我们要操作的那个窗口
if 'python' in pg.title():
break
print(pg.title())
brint_to_front
如果当前界面有很多窗口,要把某个窗口作为当前活动窗口显示出来,可以调用该窗口对应的Page对象的 bring_to_front 方法。
close
page.close()
冻结界面
在浏览器控制台输入
setTimeout(function(){debugger}, 5000)
截屏
# 截屏当前页面可见内容,保存到当前工作目录下的ss1.png文件中
page.screenshot(path='ss1.png')
# 截屏 完整页面,页面内容长度超过窗口高度时,包括不可见部分。👍👍
page.screenshot(path='ss1.png', full_page=True)
完整demo
from playwright.sync_api import sync_playwright
with sync_playwright() as p:
browser = p.chromium.launch(headless=False)
context = browser.new_context()
page = context.new_page()
page.goto('https://www.baidu.com')
# 输入框
page.locator('#kw').fill('python')
# 点击搜索
page.click('#su')
# 等待网络空闲状态
page.wait_for_load_state('networkidle')
# 截屏
page.screenshot(path='ss1.png')
page.screenshot(path='ss2.png', full_page=True)
input('浏览器即将关闭...')
browser.close()
拖拽
from playwright.sync_api import sync_playwright
with sync_playwright() as p:
browser = p.chromium.launch(headless=False)
context = browser.new_context()
page = context.new_page()
page.goto('https://www.baidu.com')
input('输入回车继续...')
# 选中百度热搜的文本
page.locator('.title-content-title').first.select_text()
input('输入回车继续...')
# 拖拽到搜索框中
page.drag_and_drop('.title-content-title', '#kw')
input('浏览器即将关闭...')
browser.close()
或者使用 locator
中的方法
from playwright.sync_api import sync_playwright
with sync_playwright() as p:
browser = p.chromium.launch(headless=False)
context = browser.new_context()
page = context.new_page()
page.goto('https://www.baidu.com')
input('输入回车继续...')
# 选中百度热搜的文本
lc = page.locator('.title-content-title').first
# 选中文本
lc.select_text()
input('输入回车继续...')
# 拖拽到搜索框中
lc.drag_to(page.locator('#kw'))
input('浏览器即将关闭...')
browser.close()
弹出对话框
alert
from playwright.sync_api import sync_playwright
pw = sync_playwright().start()
browser = pw.chromium.launch(headless=False)
page = browser.new_page()
page.goto("https://www.byhy.net/cdn2/files/selenium/test4.html")
# 处理 弹出对话框 的 回调函数
def handleDlg(dialog):
# 等待1秒
page.wait_for_timeout(1000)
# 点击确定
dialog.accept()
# 打印 弹出框 提示信息
print(dialog.message)
# 设置弹出对话框事件回调函数
page.on("dialog", handleDlg )
# 点击 alert 按钮
page.locator('#b1').click()
处理函数中被回调时,会传入 Dialog 对象
confirm
accept
方法作用等同于点击确定按钮
dismiss
方法作用等同于点击取消按钮
message
属性就是对话框界面的提示信息字符串
dialog.dismiss() # 取消
prompt
dialog.accept('hello world') # 输入文本
其他技巧
窗口最大化及debug开发
使用pycharm并使用debug启动
from playwright.sync_api import sync_playwright
with sync_playwright() as p:
browser = p.chromium.launch(args=['--start-maximized'], headless=False)
context = browser.new_context(no_viewport=True)
page = context.new_page()
page.goto('https://www.baidu.com')
# 先进行高亮显示, 再进行debug计算编写
page.locator('#kw').highlight()
wait_for_load_state() 的状态
- “load” 等待页面所有资源加载完成
- “domcontentloaded” 等待DOM内容加载完成
- “networkidle” 等待网络空闲
page.wait_for_load_state('load')
page.wait_for_load_state('domcontentloaded')
page.wait_for_load_state('networkidle')