Selenium 自動化 —— 一篇文章徹底搞懂XPath

?更多關于Selenium的知識請訪問“蘭亭序咖啡”的專欄:專欄《Selenium 從入門到精通》


文章目錄

前言

一、什么是xpath?

二、XPath 節點

三. 節點的關系

1. 父(Parent)

2. 子(Children)

3. 同胞(Sibling)

4. 先輩(Ancestor)

5. 后代(Descendant)

四. 路徑表達式

五. 謂語(Predicates)

六.?軸(Axes)

七. XPath 示例

1.?絕對路徑

2.?所有位置元素

3. 使用謂語

4.?通過@根據屬性篩選

5.?通過屬性值篩選

6.?元素計數器

7.?根據標簽名篩選

8.?函數—包含 contains

9.?函數—字符串長度

10.?邏輯或

11.?軸

12.?根據符合條件的子節點選父節點

八. Selenium 中使用XPath

總結


前言

如何定位一個XML(尤其是HTML)中的一個節點?前文我們學習了Selenium的常用的幾種選擇器,相比其它幾種比較簡單的比如id選擇器、name選擇器等外,最強大也是我們使用最頻繁的是xpath選擇器

本文,我們就對xpath進行全面的學習。


一、什么是xpath?

XPath 是一門在 XML 文檔中查找信息的語言。XPath 可用來在 XML 文檔中對元素和屬性進行遍歷。(簡單說就是在一個龐大復雜的XML中找到一個特定節點

而我們的 HTML 就是一種特殊的XML。所以 XPath 當然也可以用來對 HTML 元素和屬性進行遍歷。

XPath 使用路徑表達式來選取 XML 文檔中的節點或者節點集。

/html/body/div[1]/div[2]/div[1]/input

這些路徑表達式和我們在常規的電腦文件系統中看到的表達式非常相似。

/usr/local/apache/log/

二、XPath 節點

在 XPath 中,有七種類型的節點:元素、屬性、文本、命名空間、處理指令、注釋以及根節點。?

下面我們對每種節點介紹。

XPath 是對 XML 的操作,但是我們用得比較多的是 HTML,所以下面的代碼都會以 HTML 來演示。

<html xmlns:example="http://www.example.com">
<head>
<meta charset="utf-8">
<title>菜鳥教程(runoob.com)</title>
</head>
<body><!-- 測試 HTML -->
<h1 name="header">我的第一個標題</h1><p>我的第一個段落。</p></body>
</html>

對于上面的代碼:

  1. <html> 就是根節點
  2. 每個標簽都是一個元素,比如:<h1>我的第一個標題</h1>
  3. ?<h1 name="header">中的name=“header”就是一個屬性
  4. <p>我的第一個段落。</p> 中的“我的第一個段落。”就是文本
  5. <html xmlns:example="http://www.example.com">中的namespace就是命名空間
  6. <!-- 測試 HTML -->就是一個注釋
  7. 處理指令一般不怎么常用,如果在Vue中<div v-if="show">會比較常見。

特別注意:節點和元素的區別:

  • 節點是很廣泛的概念,包括了元素、屬性、文本、命名空間、處理指令、注釋以及根節點
  • 元素只是節點的一種,屬性也是一種節點,元素通常是html標簽對!
  • 后面會介紹 * 表示所有元素,而node()表示任意節點。

三. 節點的關系

人和人之間有關系,比如父子,兄弟等,節點同樣有這些關系

這些關系可以幫我們定位一個節點。

1. 父(Parent)

每個元素都只有一個父節點。

  • coffe的父節點是list
  • list的父節點是drink

但是注意:coffe只有一個父節點,drink不是coffe的父節點。

<div class="food"><div class="drink"><ol class="list"><li item="coffe">Coffee</li><li item="tea">Tea</li><li item="milk">Milk</li></ol></div>
</div>

2. 子(Children)

每個節點都有零個、一個或多個子節點。

  • food的子節點是drink
  • list的子節點有3個,分別是coffe、tea和milk
  • coffe沒有子節點

特別注意:coffe不是food和drink的子節點。

<div class="food"><div class="drink"><ol class="list"><li item="coffe">Coffee</li><li item="tea">Tea</li><li item="milk">Milk</li></ol></div>
</div>

3. 同胞(Sibling)

擁有相同父節點的節點。

  • coffe、tea、milk他們的父節點都是list,所以他們是同胞節點。
  • drink只有list一個子節點,所以list沒有同胞節點。
<div class="food"><div class="drink"><ol class="list"><li item="coffe">Coffee</li><li item="tea">Tea</li><li item="milk">Milk</li></ol></div>
</div>

4. 先輩(Ancestor)

某節點的父、父的父……

  • coffe的先輩節點有list、drink和food
<div class="food"><div class="drink"><ol class="list"><li item="coffe">Coffee</li><li item="tea">Tea</li><li item="milk">Milk</li></ol></div>
</div>

5. 后代(Descendant)

某個節點的子,子的子,等等。

  • food的后代節點有drink、list,還有coffe、tea、milk
<div class="food"><div class="drink"><ol class="list"><li item="coffe">Coffee</li><li item="tea">Tea</li><li item="milk">Milk</li></ol></div>
</div>

四. 路徑表達式

XPath 使用路徑表達式在 XML 文檔中選取節點

最常用的路徑表達式
路徑表達式作用示例
nodename選取此節點的所有子節點。

input:選擇所有<input>節點的所有子節點。

/

從根節點選取。

也就是絕對路徑。

/html:選擇根節點,網頁的根節點都是<html>節點。

//

從匹配選擇的當前節點選擇文檔中的節點,而不考慮它們的位置。

也就是相對路徑。

//input:選中所有<input>節點。
.選取當前節點。
..選取當前節點的父節點。
@選取屬性。//@id:選中所有有id屬性的節點。????????
*匹配任何元素

//*:任意元素的節點

//@*:屬性為任意值的節點,換句話說就是有屬性的節點,比如<html>和<body>這種節點不會被選中。

node()

匹配任何類型的節點

(特別區別*,元素是特殊的節點,屬性也是節點)

//node():選中任意節點
|使用“|”運算符,可以選取若干個路徑。也就是或//input | //ul:選中所有的<input>或者<ul>節點

是不是和 Linux 的路徑語法很類似!區別在于一個是選擇目錄,一個是選擇節點

//div/span 和 //div//span 有什么區別?(非常重要)

  • //div/span:選擇div元素的子節點中的span
  • //div//span:選擇div元素的后代節點中的span

比如對于下面的html,使用“//div/span”只能選中一個span,但是使用"//div//span"可以選中兩個span!

<div><span>Hello<span><ul><span>World</span></ul>
<div>

節點和元素的區別?(特別重要)

以 * 和 node()為例:

  • //*:選中了5個元素:(5) [html, head, title, body, div.box]
  • //node():選中了8個節點:(8) [<!DOCTYPE html>, html, head, title, text, body, div.box, text]
<!DOCTYPE html>
<html><head><title>預定</title></head><body><div class="box">Hello</div></body>
</html>

五. 謂語(Predicates)

謂語用來查找某個特定的節點或者包含某個指定的值的節點。謂語被嵌在方括號中。

是不是不太好理解。

其實,我們學習中文或者英文語法的時候,也接觸過 主+謂+賓語 的結構,這和XPath的謂語很類似。

謂語(Predicate) 是對主語動作狀態或特征的陳述或說明,指出"做什么(what to do)" , "是什么(what is this)"。

謂語動詞的位置一般在主語之后, 經常用動詞和形容詞搭配來充當謂語動詞。

比如:

  • 選擇div的第二個子節點
  • 選擇有id屬性的div節點
  • 數值大于35的節點
  • ……

有了這些謂詞,我們可以更精確的定位到特定的節點

六.?軸(Axes)

前面介紹了節點之間的關系,比如父子關系、兄弟關系等。

Xpath 使用軸?定義了節點與當前節點之間的關系,相當于節點的運動路徑。每一個軸都有一個基本節點類型。

?在 XPath 中,我們使用軸(如 child、parent、attribute 等)來定位節點

用關系來定位節點!

軸名稱結果
ancestor選取當前節點的所有先輩(父、祖父等)。
ancestor-or-self選取當前節點的所有先輩(父、祖父等)以及當前節點本身。
attribute選取當前節點的所有屬性。
child選取當前節點的所有子元素。
descendant選取當前節點的所有后代元素(子、孫等)。
descendant-or-self選取當前節點的所有后代元素(子、孫等)以及當前節點本身。
following選取文檔中當前節點的結束標簽之后的所有節點。
namespace選取當前節點的所有命名空間節點。
parent選取當前節點的父節點。
preceding選取文檔中當前節點的開始標簽之前的所有節點。
preceding-sibling選取當前節點之前的所有同級節點。
self選取當前節點。

語法規則:

軸名稱::節點測試[謂語]

下面列舉一些實例來說明!!!

例子結果
//div//child::input

選取所有屬于div節點的子元素的 input 節點。

不過直接用簡單的寫法就行了://div//input

//input//attribute::id

選取所有input節點的 id?屬性。(屬性也是一種節點!

比如<input id="username" name="uname">?

//ul//child::*

選取當前節點的所有子元素。(因為使用了//相對路徑, 所以是所有后代節點

如果 //ul/child::*? 因為是 / 絕度路徑, 所以選中所有子節點

//input//attribute::*

選取input節點的所有屬性。

<input id="username" name="uname" class="big">

//a//child::text()

選取a節點的所有文本子節點。

簡單寫法://a/text()

比如:<a>測試</a>? <a>Hello</a>

//a//child::node()

選取a節點的所有子節點。(注意是節點,所以也包括元素,而且使用的//相對,所以所有后代的節點)

//ul//descendant::input選取ul節點的所有 input 后代節點。
//input//ancestor::li選擇input節點的所有 li 先輩節點。
ancestor-or-self::book選取當前節點的所有 book 先輩以及當前節點(如果此節點是 book 節點)
//ul/child::*/child::input

選取ul節點的所有 input 孫節點

相當于://ul/*/inut

所有的child::XXX 都可以直接寫XXX

比如://a//child::text()? ?--> //a//text()

? ? ? ? ? ?//div//child::input --> //div//input

七. XPath 示例

1.?絕對路徑

/html/body/div[2]/top-menu/header/div/div[1]/h1/a/img

2.?所有位置元素

//div //任意div節點
//div//img /*div的所有img后代*/

3. 使用謂語

//ul//li[1] /*選擇第一個*/
//ul//li[position() = 1] /*多種寫法*///ul//li[last()] /*選擇最后一個*/

4.?通過@根據屬性篩選

//@jscontent	/*所有帶jscontent屬性的節點*/
//span[@jscontent] /*所有帶jscontent屬性的span節點*///span[@*] /*所有帶任意屬性的span節點*///div[not(@*)] /*沒有任何屬性的div節點*/
//div[not(@id)] /*沒有id屬性的div節點*/

5.?通過屬性值篩選

//span[@class='currency']
//span[normalize-space(@class)='currency']  /*去掉前后空格后再比較*/

6.?元素計數器

//ul[count(li)=5] /*有5個li的ul*///*[count(*)=3] /*有3個子元素的任意節點*/

7.?根據標簽名篩選

//*[name()='span']	/*等同于//span*
//span//*[starts-with(name(), 'scri')]  /*標簽名以scri開頭的標簽*/
//*[contains(name(), 'pt')] /*標簽名包含pt的標簽*/

8.?函數—包含 contains

//div[contains(@class, 'rowFlightItem')]

如果使用全匹配是獲取不到的//div[@class, 'tripselector_inbound'] 除非//div[@class, 'tripselector_inbound ng-star-inserted']

但是要特別注意,模糊匹配可能會匹配到不期望的對象

//flight//div[contains(@class, 'row')]

9.?函數—字符串長度

//*[string-length(name()) = 3] /*標簽名字為3個字符串的節點,比如div,img*/

10.?邏輯或

//ul | //button /*ul標簽或button*/

11.?軸

//div//child::ul  /*選擇子節點是ul的div*///div/ul /*簡潔寫法*/

注意child和descendant的區別,一個兒子,一個是后代。兒子也是后代

后代節點軸

//div//descendant::*  /*選擇div下面的所有元素*///div//*

后面的兄弟節點

//ul//li/following-sibling::*  /*ul下第一個后面的子節點!*/

12.?根據符合條件的子節點選父節點

//table[.//th[@scope="colgroup" and normalize-space(.)="成人"]]
.//tr[contains(@class, 'taxesOrFees-tr') and (.//td)]  /*子節點有td的tr*/
<table class="table"><caption class="">Departure flight - adult prices resume table</caption><tbody><tr class="colgroup_title"><th colspan="2" scope="colgroup">成人</th></tr>

八. Selenium 中使用XPath

使用非常簡單,就是By.xpath()方法即可:

WebElement element = driver.findElement(By.xpath("//input[@id='username']"));


總結

以上就是今天要講的內容,本文系統全面的介紹了Xpath,從什么是Xpath講起,到Xpath的基本概念,最后到語法和實戰!相信這會讓你在使用 Selenium 時如虎添翼!關注蘭亭序咖啡的博客,我們一起對 Selenium 學習和探討!

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/11048.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/11048.shtml
英文地址,請注明出處:http://en.pswp.cn/web/11048.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

力扣:48. 旋轉圖像(Java)

目錄 題目描述&#xff1a;輸入&#xff1a;輸出&#xff1a;代碼實現&#xff1a; 題目描述&#xff1a; 給定一個 n n 的二維矩陣 matrix 表示一個圖像。請你將圖像順時針旋轉 90 度。 你必須在 原地 旋轉圖像&#xff0c;這意味著你需要直接修改輸入的二維矩陣。請不要 使…

LangChain:模型 I/O 封裝使用解析和感觸

目錄 模型 API&#xff1a;LLM vs. ChatModel OpenAI 模型封裝 多輪對話 Session 封裝 換個國產模型 模型的輸入與輸出 Prompt 模板封裝 PromptTemplate ChatPromptTemplate MessagesPlaceholder 從文件加載 Prompt 模板 TXT模板 Yaml模板 Json模板 輸出封裝 Out…

mediasoup源碼(一)編譯及部署

基本介紹 mediasoup是一個sfu架構的流媒體服務器&#xff0c;讀者可以根據需要選擇不同的編譯方式。如果只需要學習c流媒體傳輸部分&#xff0c;則選擇mediasoup&#xff0c;如果需要學習mediasoup整個demo&#xff0c;并做演示&#xff0c;則可以選擇mediasoup-demo&#xff…

is和==的關系

Python中is和的關系 is判斷兩個變量是不是指的是同一個內存地址&#xff0c;也就是通過id()函數判斷 判斷兩個變量的值是不是相同 a [1, 2, 3, 4] b [1, 2, 3, 4] print(id(a)) # 2298268712768 print(id(b)) # 2298269716992 print(a is b) # False print(a b) # Tr…

目標檢測標注工具Labelimg安裝與使用

目錄 一、安裝Labelimg與打開 二、使用 1、基本功能介紹 2、快捷鍵 3、狀態欄的工具 三、附錄 1、YOLO模式創建標簽的樣式 2、create ML模式創建標簽的樣式 3、PascalVOC模式創建標簽的樣式 一、安裝Labelimg與打開 labelimg是一款開源的數據標注工具&#xff0c;可以…

51基于單片機的溫室大棚系統設計

設計摘要&#xff1a; 本設計旨在基于51單片機和藍牙技術&#xff0c;實現一個功能完善的溫室大棚系統。該系統具備以下主要功能&#xff1a;首先&#xff0c;通過連接的顯示屏能夠實時地顯示當前的溫度和濕度信息&#xff0c;方便用戶了解溫室內的環境變化。其次&#xff0c;…

ctfshow web271--web273

web271 laravel5.7反序列化漏洞 define(LARAVEL_START, microtime(true));/* |-------------------------------------------------------------------------- | Register The Auto Loader |-------------------------------------------------------------------------- | |…

mysql IF語句,模糊檢索

使用MySQL IF語句完成條件檢索 IF(expr1,expr2,expr3)&#xff0c;expr1如果滿足條件就用expr2&#xff0c;否則用expr3 SELECTa.*,count(*) AS stdSum FROMidb_std_power_engin_v1 a WHERE1 1 AND (IF( KV IS NOT NULL, a.NAME REGEXP KV, 1 1 ) ORIF( KV IS NOT NULL, …

凸優化理論學習二|凸函數及其相關概念

系列文章目錄 凸優化理論學習一|最優化及凸集的基本概念 文章目錄 系列文章目錄一、凸函數&#xff08;一&#xff09;凸集&#xff08;二&#xff09;凸函數的定義及舉例&#xff08;三&#xff09;凸函數的證明1、將凸函數限制在一條直線上2、判斷函數是否為凸函數的一階條件…

如何做筆記

鏈接&#xff1a; 程序員讀技術類書籍如何做筆記&#xff1f; - 知乎 我是如何寫好一篇技術博客的 - 簡書 技術博客&#xff0c;該寫些什么&#xff1f; - 知乎 前言 最近翻翻以前的博客和筆記&#xff0c;都覺得寫的不好。工作這么多年&#xff0c;其實一直都有想做成知識系列…

貝葉斯分類器詳解

1 概率論知識 1.1 先驗概率 先驗概率是基于背景常識或者歷史數據的統計得出的預判概率&#xff0c;一般只包含一個變量&#xff0c;例如P(A)&#xff0c;P(B)。 1.2 聯合概率 聯合概率指的是事件同時發生的概率&#xff0c;例如現在A,B兩個事件同時發生的概率&#xff0c;記…

Python: 獲取時間

from datetime import datetime, timedelta# 獲取當前時間 current_time datetime.now() print(f"current_time {current_time}")# 獲取時分秒部分 time current_time.time() print(f"time {time}")# 獲取當前時間,只要日期部分 current_date current…

華為交換機配置導出備份python腳本

一、腳本編寫思路 &#xff08;一&#xff09;針對設備型號 主要針對華為&#xff08;Huawei&#xff09;和華三&#xff08;H3C&#xff09;交換機設備的配置備份 &#xff08;二&#xff09;導出前預處理 1.在配置導出前&#xff0c;自動打開crt軟件或者MobaXterm軟件&am…

掌握MySQL執行計劃分析【Explain】

前言 MySQL是一個強大的關系型數據庫管理系統&#xff0c;其高效執行SQL查詢的能力是其核心價值之一。然而&#xff0c;當查詢變得復雜或者數據量急劇增長時&#xff0c;SQL查詢的性能問題往往成為我們不得不面對的挑戰。為了深入了解查詢的執行過程并找到性能瓶頸&#xff0c…

Modbus通訊協議初學

目錄 Modbus通訊協議初學什么是Modbus?Modbus用來做什么?4個種類的寄存器協議速記功能碼Modbus 報文幀示例解讀 Modbus通訊協議初學 什么是Modbus? 顧名思義,它是一個bus,即總線協議。比如串口協議、IIC協議、SPI都是通訊協議。你接觸到這種協議,相信你所處的行業是工業方…

如何自定義Linux命令

說明&#xff1a;本文介紹如何將自己常用的命令設置為自定義的命令&#xff0c;以下操作在阿里云服務器CentOS上進行。 修改配置文件 修改配置文件前&#xff0c;先敲下面的命令查看當前系統配置的shell版本 echo $SHELL或者 echo $0區別在于&#xff0c;$SHELL查看的是系統…

落雪音樂 超好用的桌面端音樂播放器

之前一直都是充某Q音樂的會員&#xff0c;突然不想氪金了&#xff0c;終于找到一個開源的音樂播放器&#xff0c;在此先給落雪無痕大佬跪了 太愛了 簡直白嫖怪的福音 話不多說&#xff0c;直接上操作&#xff1a;解壓密碼&#xff1a;www.1234f.com下載地址&#xff1a;極速云…

圖片批量管理邁入智能新時代:一鍵輸入關鍵詞,自動生成并保存驚艷圖片,輕松開啟創意之旅!

在數字化時代&#xff0c;圖片已成為我們表達創意、記錄生活、傳遞信息的重要工具。然而&#xff0c;隨著圖片數量的不斷增加&#xff0c;如何高效、便捷地管理這些圖片&#xff0c;卻成為了一個令人頭疼的問題。 第一步&#xff0c;進入首助編輯高手主頁面&#xff0c;在上方…

簡單的Python示例母親節的祝福

在Python中&#xff0c;我們通常不會直接編寫HTML源碼&#xff0c;但我們可以編寫一個Python腳本來生成或發送包含母親節祝福的HTML內容。以下是一個簡單的Python示例&#xff0c;它使用字符串拼接來創建一個簡單的HTML頁面&#xff0c;其中包含母親節的祝福。 # 定義一個包含…

【AMBA Bus ACE 總線 9.1 -- Non-cache Master 寫操作 詳細介紹】

請閱讀【AMBA Bus ACE 總線與Cache 專欄 】 歡迎學習:【嵌入式開發學習必備專欄】 文章目錄 Non-cache MasterACE 和系統級緩存一致性ACE 非緩存主控(Non-cacheable Master)Non-cache Master ARM的ACE(AXI Coherency Extension)是一種用于增強系統級緩存一致性的接口規范…