python中playwright實(shí)現(xiàn)定位和點(diǎn)擊的多種方法
在 Playwright 中,實(shí)現(xiàn)定位 (Locating) 和點(diǎn)擊 (Clicking) 是最基本也是最重要的操作。你需要先準(zhǔn)確地找到頁面上的目標(biāo)元素,然后才能對(duì)其執(zhí)行點(diǎn)擊操作。
Playwright 提供了多種強(qiáng)大的定位器 (Locators) 來幫助你準(zhǔn)確地找到元素,并且它有智能的自動(dòng)等待 (Auto-wait) 機(jī)制,這意味著你通常不需要手動(dòng)添加等待元素出現(xiàn)的代碼。
定位 (Locating) 元素
Playwright 推薦使用其內(nèi)置的可見性定位器,它們更健壯,更接近用戶感知,并且與可訪問性最佳實(shí)踐對(duì)齊。
以下是幾種常用的定位方法:
1.按角色定位 (get_by_role)-推薦!
這是 Playwright 最推薦的定位方式。它基于元素的可訪問性角色 (ARIA Role) 來定位,模擬用戶如何感知頁面。例如,一個(gè)按鈕就是 role='button',一個(gè)鏈接是 role='link'。
- 優(yōu)點(diǎn): 最健壯,不易受頁面 HTML 結(jié)構(gòu)變化影響,與用戶感知最接近。
- 用法:
page.get_by_role("role", name="text", exact=False)role:元素的 ARIA 角色(如 “button”, “link”, “textbox”, “checkbox”, “heading” 等)。name:元素的可訪問名稱,通常是用戶在界面上看到的文本。exact=False:如果為True,則名稱必須精確匹配;如果為False(默認(rèn)),則允許部分匹配。
示例:
# 定位一個(gè)文本為 "登錄" 的按鈕
page.get_by_role("button", name="登錄").click()
# 定位一個(gè)文本為 "用戶協(xié)議" 的鏈接
page.get_by_role("link", name="用戶協(xié)議").click()
# 定位一個(gè)文本框,其關(guān)聯(lián)的標(biāo)簽文本為 "用戶名"
page.get_by_role("textbox", name="用戶名").fill("your_username")
# 定位一個(gè)層級(jí)為 h1 的標(biāo)題,文本包含 "Playwright"
page.get_by_role("heading", name="Playwright", level=1)
2.按文本定位 (get_by_text)
根據(jù)元素顯示的文本內(nèi)容來定位。
- 優(yōu)點(diǎn): 直觀,適用于文本是唯一標(biāo)識(shí)的情況。
- 用法:
page.get_by_text("text_content", exact=False)
示例:
# 定位文本為 "提交" 的任意元素
page.get_by_text("提交").click()
# 定位文本包含 "商品詳情" 的元素
page.get_by_text("商品詳情").click()
3.按標(biāo)簽文本定位 (get_by_label)
主要用于定位與 <label> 元素關(guān)聯(lián)的輸入框(input, textarea, select 等)。
- 優(yōu)點(diǎn): 健壯,當(dāng)輸入框沒有
id或name屬性時(shí)很有用。 - 用法:
page.get_by_label("label_text", exact=False)
示例:
# 定位一個(gè)被 <label>Username:</label> 關(guān)聯(lián)的輸入框
page.get_by_label("Username:").fill("my_user")
4.按占位符文本定位 (get_by_placeholder)
通過輸入框的 placeholder 屬性值來定位。
- 優(yōu)點(diǎn): 簡單直接,適用于輸入框有明確占位符的情況。
- 用法:
page.get_by_placeholder("placeholder_text", exact=False)
示例:
# 定位 placeholder 為 "請(qǐng)輸入手機(jī)號(hào)" 的輸入框
page.get_by_placeholder("請(qǐng)輸入手機(jī)號(hào)").fill("13812345678")
5.按測(cè)試 ID 定位 (get_by_test_id)
如果你的項(xiàng)目在 HTML 中使用了 data-test-id 或其他自定義測(cè)試 ID 屬性,這是最可靠的定位方式。需要開發(fā)者在頁面中預(yù)置。
- 優(yōu)點(diǎn): 最穩(wěn)定,不易受 UI 或內(nèi)容變化影響。
- 用法:
page.get_by_test_id("my_test_id")
示例:
HTML: <button data-test-id="submit-button">提交</button>
# 定位 data-test-id="submit-button" 的元素
page.get_by_test_id("submit-button").click()
6.CSS 選擇器定位 (locator("CSS_SELECTOR"))-次要選擇
當(dāng)你無法使用更語義化的定位器時(shí),可以使用傳統(tǒng)的 CSS 選擇器。
- 優(yōu)點(diǎn): 靈活,前端開發(fā)者熟悉。
- 缺點(diǎn): 依賴 HTML 結(jié)構(gòu),結(jié)構(gòu)變化容易失效。
- 用法:
page.locator("CSS_SELECTOR")
示例:
# 定位 id 為 "username" 的輸入框
page.locator("#username").fill("my_username")
# 定位 class 為 "login-btn" 的按鈕
page.locator(".login-btn").click()
# 定位父元素為 div,且 class 為 "item" 的第3個(gè) span
page.locator("div.parent .item:nth-child(3) span")
7.XPath 定位 (locator("xpath=XPATH_EXPRESSION"))-最后選擇
XPath 是一種非常強(qiáng)大的定位語言,但通常比 CSS 選擇器更復(fù)雜,且可讀性較差。在其他定位器都無法滿足需求時(shí)使用。
- 優(yōu)點(diǎn): 極其靈活,可以定位任何元素。
- 缺點(diǎn): 語法復(fù)雜,可讀性差,同樣依賴 HTML 結(jié)構(gòu)。
- 用法:
page.locator("xpath=XPATH_EXPRESSION")
示例:
# 定位文本為 "登錄" 的按鈕 (與 get_by_role("button", name="登錄") 類似)
page.locator("xpath=//button[text()='登錄']").click()
# 定位所有 div 元素中的第一個(gè)
page.locator("xpath=//div[1]")
點(diǎn)擊 (Clicking) 元素
一旦你使用上述方法定位到了一個(gè)元素,你就可以直接對(duì)其調(diào)用 .click() 方法。
Playwright 的 .click() 方法是智能的,它會(huì)自動(dòng)等待:
- 元素出現(xiàn)在 DOM 中。
- 元素變得可見(不是隱藏的)。
- 元素變得可用(未禁用)。
- 元素在點(diǎn)擊位置沒有被其他元素遮擋。
- 元素變得穩(wěn)定(不再移動(dòng))。
只有當(dāng)所有這些條件都滿足時(shí),Playwright 才會(huì)嘗試點(diǎn)擊。
基本用法:
# 定位并點(diǎn)擊一個(gè)按鈕
page.get_by_role("button", name="提交").click()
# 定位一個(gè) CSS 選擇器,并點(diǎn)擊它
page.locator(".my-custom-button").click()
示例:定位并點(diǎn)擊一個(gè)登錄按鈕
假設(shè)你有一個(gè)登錄頁面,上面有一個(gè)用戶名輸入框、密碼輸入框和一個(gè)“登錄”按鈕。
from playwright.sync_api import Playwright, sync_playwright, expect
def login_example(playwright: Playwright):
browser = playwright.chromium.launch(headless=False)
page = browser.new_page()
# 導(dǎo)航到示例登錄頁 (請(qǐng)?zhí)鎿Q為實(shí)際的登錄頁URL)
page.goto("https://example.com/login")
# 1. 定位并填充用戶名輸入框
# 假設(shè)輸入框的 placeholder 是 "請(qǐng)輸入用戶名"
# 或者其關(guān)聯(lián)的 label 文本是 "用戶名"
page.get_by_placeholder("請(qǐng)輸入用戶名").fill("myusername")
# 或者如果有一個(gè) label:
# page.get_by_label("用戶名").fill("myusername")
# 2. 定位并填充密碼輸入框
# 假設(shè)輸入框的 placeholder 是 "請(qǐng)輸入密碼"
page.get_by_placeholder("請(qǐng)輸入密碼").fill("mypassword")
# 或者如果有一個(gè) label:
# page.get_by_label("密碼").fill("mypassword")
# 3. 定位并點(diǎn)擊登錄按鈕
# 假設(shè)登錄按鈕的文本是 "登錄" 并且它是一個(gè) button 角色
page.get_by_role("button", name="登錄").click()
# (可選) 驗(yàn)證登錄是否成功,例如等待頁面跳轉(zhuǎn)或特定元素出現(xiàn)
expect(page).to_have_url("https://example.com/dashboard")
print("登錄成功并跳轉(zhuǎn)到 Dashboard 頁面")
browser.close()
with sync_playwright() as playwright:
login_example(playwright)
調(diào)試輔助:Playwright Inspector
在不確定如何定位元素時(shí),Playwright Inspector 是你最好的朋友。
- 運(yùn)行你的腳本,并加上
PWDEBUG=1:PWDEBUG=1 python your_script.py
- 你的腳本會(huì)在每一步操作前暫停,并彈出一個(gè) Inspector 窗口。
- 在 Inspector 窗口中,你可以點(diǎn)擊頁面上的元素,它會(huì)自動(dòng)生成多種定位器供你選擇,包括推薦的
get_by_role、get_by_text等。這能極大地幫助你編寫正確的定位代碼。
通過這些方法,你將能夠高效地在 Playwright 中定位和點(diǎn)擊頁面上的任意元素!
在 Playwright 中,role(角色)是 Web 可訪問性(Accessibility) 中一個(gè)非常重要的概念,也是 Playwright 推薦的首選定位策略之一。它指的是 HTML 元素所扮演的語義角色,用來描述該元素在用戶界面中的用途和行為。
什么是 Web 可訪問性中的role?
想象一下,你正在瀏覽一個(gè)網(wǎng)頁。作為有視力的用戶,你可以看到一個(gè)按鈕,上面寫著“提交”,或者一個(gè)鏈接,上面寫著“了解更多”。但是,對(duì)于使用屏幕閱讀器(Screen Reader)的視障用戶來說,他們無法“看”到這些視覺元素。屏幕閱讀器需要依靠網(wǎng)頁的語義信息來告訴用戶:“這里有一個(gè)按鈕,它的文本是‘提交’”,或者“這里有一個(gè)鏈接,它的文本是‘了解更多’”。
這個(gè)“按鈕”、“鏈接”就是元素的角色。
在 HTML 中,一些元素天生就帶有明確的角色(隱式角色):
<button>元素:其角色就是button。<a>元素:其角色通常是link。<input type="text">:其角色是textbox。<h1>到<h6>:其角色是heading。
對(duì)于沒有內(nèi)置語義的通用元素(如 <div> 或 <span>),開發(fā)者可以使用 ARIA (Accessible Rich Internet Applications) 屬性來明確地賦予它們角色,例如 <div role="button">。
Playwright 中的get_by_role()定位器
Playwright 利用了這種可訪問性信息,提供了 page.get_by_role() 這個(gè)強(qiáng)大的定位器。
為什么get_by_role()是首選?
健壯性 (Robustness):
- 不依賴 HTML 結(jié)構(gòu): 與 CSS 選擇器或 XPath 不同,
get_by_role()不依賴于 DOM 元素的id、class或具體的嵌套結(jié)構(gòu)。即使頁面的 CSS 或 HTML 布局發(fā)生變化,只要元素的語義角色和可訪問名稱不變,定位器依然有效。 - 模擬真實(shí)用戶: 它是最接近真實(shí)用戶與網(wǎng)站交互的方式。用戶不會(huì)關(guān)心按鈕的
class是什么,他們關(guān)心的是“這是一個(gè)按鈕,上面寫著什么”。
- 不依賴 HTML 結(jié)構(gòu): 與 CSS 選擇器或 XPath 不同,
可維護(hù)性 (Maintainability):
- 代碼更易讀,更直觀。
page.get_by_role("button", name="提交")比page.locator(".submit-btn.large")更清晰地表達(dá)了你想要點(diǎn)擊的是什么。 - 減少了因前端重構(gòu)而導(dǎo)致的測(cè)試中斷(flaky tests)。
- 代碼更易讀,更直觀。
可訪問性 (Accessibility):
- 鼓勵(lì)編寫更具可訪問性的 Web 應(yīng)用。當(dāng)你的測(cè)試使用
get_by_role()時(shí),實(shí)際上是在驗(yàn)證應(yīng)用程序?qū)ζ聊婚喿x器用戶是否友好。如果get_by_role()找不到元素,很可能意味著該元素對(duì)于輔助技術(shù)來說不夠清晰。
- 鼓勵(lì)編寫更具可訪問性的 Web 應(yīng)用。當(dāng)你的測(cè)試使用
get_by_role()的用法
page.get_by_role(role, name, ...) 主要需要兩個(gè)參數(shù):
role(角色名): 元素的 ARIA 角色。常見的角色有:"button": 按鈕"link": 鏈接"textbox": 文本輸入框(包括input type="text",textarea等)"checkbox": 復(fù)選框"radio": 單選按鈕"heading": 標(biāo)題(如<h1>,<h2>等)"combobox": 下拉選擇框(帶有文本輸入功能的)"listbox": 列表選擇框(如<select size="multiple">)"option": 列表或下拉框中的選項(xiàng)"tab": 選項(xiàng)卡"dialog": 對(duì)話框/模態(tài)框- …等等,完整的列表請(qǐng)參考 ARIA 規(guī)范或 Playwright 文檔。
name(可訪問名稱): 這是用戶在視覺上或通過屏幕閱讀器聽到的元素文本。- 對(duì)于按鈕和鏈接,通常是它們內(nèi)部的文本。
- 對(duì)于輸入框,通常是與之關(guān)聯(lián)的
<label>元素的文本或aria-label屬性的值。 name參數(shù)可以使用字符串,也可以使用正則表達(dá)式 (re.compile) 進(jìn)行部分匹配或更復(fù)雜的匹配。
示例:
# 定位一個(gè)文本是 "提交" 的按鈕
page.get_by_role("button", name="提交").click()
# 定位一個(gè)文本為 "隱私政策" 的鏈接
page.get_by_role("link", name="隱私政策").click()
# 定位一個(gè)標(biāo)題為 "歡迎來到我的網(wǎng)站" 的 h1 標(biāo)簽
page.get_by_role("heading", name="歡迎來到我的網(wǎng)站", level=1).click()
# 定位一個(gè)與標(biāo)簽 "用戶名" 關(guān)聯(lián)的文本輸入框,并填充
page.get_by_role("textbox", name="用戶名").fill("your_username")
# 定位一個(gè)包含 "Playwright" 字樣的按鈕 (使用正則表達(dá)式進(jìn)行部分匹配)
import re
page.get_by_role("button", name=re.compile("Playwright")).click()
何時(shí)使用get_by_role()?
始終嘗試優(yōu)先使用 get_by_role()。
只有當(dāng)以下情況發(fā)生時(shí),才考慮使用其他定位器(如 get_by_text, get_by_label, get_by_test_id 或最后的 CSS/XPath):
- 元素沒有明確的可訪問性角色或名稱。
- 頁面上的多個(gè)元素具有相同的角色和名稱,導(dǎo)致
get_by_role()定位不唯一。 - 你需要根據(jù)元素的特定視覺屬性或復(fù)雜層級(jí)關(guān)系進(jìn)行定位(這通常是糟糕的測(cè)試實(shí)踐,但有時(shí)無法避免)。
到此這篇關(guān)于python中playwright實(shí)現(xiàn)定位和點(diǎn)擊的多種方法的文章就介紹到這了,更多相關(guān)playwright 定位和點(diǎn)擊內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
python腳本實(shí)現(xiàn)驗(yàn)證碼識(shí)別
這篇文章主要為大家詳細(xì)介紹了python腳本實(shí)現(xiàn)驗(yàn)證碼識(shí)別的實(shí)現(xiàn)代碼,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-06-06
Python對(duì)圖片和js前端進(jìn)行加密解密的技術(shù)實(shí)現(xiàn)
Python可以對(duì)圖片進(jìn)行加密,前端JS進(jìn)行解密,但需滿足算法兼容性、密鑰安全傳遞、數(shù)據(jù)格式處理三大核心條件,這篇文章從技術(shù)實(shí)現(xiàn)、安全性、典型方案三方面詳細(xì)說明,需要的朋友可以參考下2025-09-09
Python處理JSON的完全指南:從基礎(chǔ)到實(shí)戰(zhàn),掌握數(shù)據(jù)交換核心技能
本文將從?JSON?與?Python?的類型映射講起,帶你理解序列化與反序列化的底層邏輯,然后通過實(shí)戰(zhàn)案例演示如何解析?API?數(shù)據(jù)、處理自定義對(duì)象,最后總結(jié)出?3?個(gè)避坑技巧2026-06-06
Django2.1集成xadmin管理后臺(tái)所遇到的錯(cuò)誤集錦(填坑)
這篇文章主要介紹了Django2.1集成xadmin管理后臺(tái)所遇到的錯(cuò)誤集錦(填坑),小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2018-12-12
Python基于FastAPI和WebSocket實(shí)現(xiàn)實(shí)時(shí)聊天應(yīng)用
這篇文章主要為大家詳細(xì)介紹了Python如何基于FastAPI和WebSocket實(shí)現(xiàn)實(shí)時(shí)聊天應(yīng)用,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下2025-04-04

