Python 爬蟲之 XPath 元素定位

XPath 簡介

XPath (XML Path Language) 最初是為了在 XML 文檔中進行導航而設計的語言,后來被廣泛應用于 HTML 文檔的解析。與 BeautifulSoup 相比,XPath 有以下特點:

  • 語法強大:可以通過簡潔的表達式精確定位元素
  • 跨平臺性:幾乎所有編程語言都有 XPath 的實現
  • 靈活性高:可以通過各種軸、謂詞和函數構建復雜的選擇條件

在 Python 中,我們主要通過 lxml 或者 selenium 庫來使用 XPath 功能。可以通過 pip 安裝下面的依賴包。

pip install lxml
pip install selenium

XPath 測試工具

瀏覽器

用瀏覽器測試驗證 XPath 最直觀,最方便,優先推薦這種方式。比如在百度熱搜?百度熱搜 測試?XPath。

在瀏覽器開發者工具的 Elements 中按?Ctrl + F,在搜索框中輸入 XPath 。比如查找百度熱搜標題,XPath 正確的話,會在頁面高亮顯示對應的元素。

lxml?

Python 的 lxml 庫提供了強大的 XPath 支持。比如以下用來解析提取熱搜新聞標題。

from lxml import etree
import requests# 獲取HTML內容
url = "https://top.baidu.com/board?tab=realtime"
response = requests.get(url)
html_text = response.text# 解析HTML
# html = etree.HTML(html_text)
# 或者從文件加載HTML
html = etree.parse('百度熱搜.html', etree.HTMLParser())# 使用XPath提取數據
titles = html.xpath('//div/a/div[@class="c-single-text-ellipsis"]/text()')  # 獲取標題文本
for index, title in enumerate(titles):print(f"第 {index + 1} 條新聞;新聞標題:{title}")
print("===熱搜標題提取正常===")
第 1 條新聞;新聞標題:去“三好”鄰邦家做客
第 2 條新聞;新聞標題:拜登:特朗普太掉價了
第 3 條新聞;新聞標題:央行1萬億元大紅包對普通人影響多大
...
第 48 條新聞;新聞標題:世界人形機器人運動會將在北京舉辦
第 49 條新聞;新聞標題:蘋果探索在瀏覽器中加入AI搜索功能
第 50 條新聞;新聞標題:專家解讀:為何央行此時宣布降準降息
第 51 條新聞;新聞標題:騎士G2冤死 裁判報告公布三次漏判
===熱搜標題提取正常===

selenium

Python 的 selenium 庫提也供了強大的 XPath 支持。比如使用 RPA 流程自動化爬取數據的時候,總避免不了通過 XPath 去定位和查詢元素。以下用來解析提取熱搜新聞標題。

from selenium import webdriver
from selenium.webdriver.common.by import Bydef init_driver():option = webdriver.ChromeOptions()driver = webdriver.Chrome(r'./driver/chromedriver.exe', options=option)driver.maximize_window()return driverdef main():driver = init_driver()url = r'file:///E:\lky_project\tmp_project\百度熱搜.html'driver.get(url)try:xpath_titles = '//div/a/div[@class="c-single-text-ellipsis"]'titles = driver.find_elements(By.XPATH, xpath_titles)for index, title in enumerate(titles):print(f"第 {index + 1} 條新聞;新聞標題:{title.text}")print("===熱搜標題提取正常===")except Exception as e:print("===熱搜標題提取報錯===", e)returnif __name__ == '__main__':main()
第 1 條新聞;新聞標題:去“三好”鄰邦家做客
第 2 條新聞;新聞標題:拜登:特朗普太掉價了
第 3 條新聞;新聞標題:央行1萬億元大紅包對普通人影響多大
...
第 48 條新聞;新聞標題:世界人形機器人運動會將在北京舉辦
第 49 條新聞;新聞標題:蘋果探索在瀏覽器中加入AI搜索功能
第 50 條新聞;新聞標題:專家解讀:為何央行此時宣布降準降息
第 51 條新聞;新聞標題:騎士G2冤死 裁判報告公布三次漏判
===熱搜標題提取正常===

XPath 常用函數?

contains()

contains()?函數用于判斷某個屬性的取值中是否包含指定的字符串。其語法格式如下:

contains(@attribute, "substring")
    • @attribute:表示要過濾的屬性名稱,屬性名稱前需加上@符號。
    • substring:表示要判斷是否包含的字符串。

    在自動化測試中,contains?函數特別適用于定位那些屬性值不固定的元素。例如,某個元素的id?屬性值在每次頁面刷新時都會發生變化,但其中某些字符是固定的。通過?contains?函數,可以基于這些固定的字符進行定位。

    比如頁面中查找?name?屬性中包含?username?的?input?元素:

    //input[contains(@name, 'username')]

    starts-with()

    與 contains() 類似,只不過是限定指定開頭的屬性或者文本。

    //div/a/div[starts-with(text(), "  國防部")]

    ends-with()

    限定指定結尾的屬性或者文本(部分瀏覽器不一定支持,要想兼容性更強的話建議最好少用)

    //div/a/div[ends-with(text(), "熱烈歡迎 ")]

    position()

    position()?函數用于選取指定位置的元素。其語法格式如下。

    //element[position() < number]
    //element[position() <= number]
    //element[position() = number]
    //element[position() > number]
    //element[position() >= number]
    • position():表示元素的序號,從1開始計數。
    • number:表示設定的閾值。

    比如:

    //element[1]

    等價于:

    //element[position() = 1]

    ?比如頁面中有多個?input?元素,我們希望選取前兩個?input?元素。

    //input[position()<3]

    last()

    last()?函數用于選取從后往前數的元素。其語法格式如下:

    //element[last() - number]
    
      • last():表示匹配元素的總數。
      • number:表示從后往前數的元素位置。

      假設頁面中有多個?input?元素,我們希望選取最后一個?input?元素:

      //input[last()]
      

        如果希望選取倒數第二個?input?元素:

        //input[last() - 1]

        count()?

        count() 函數通過對子元素指定類型節點進行統計來限定父元素的選取。語法格式如下:

        //element[count(sub_element) < number]
        //element[count(sub_element) <= number]
        //element[count(sub_element) = number]
        //element[count(sub_element) > number]
        //element[count(sub_element) >= number]
        • count(sub_element):表示 element 元素 下 sub_element 的數目。
        • number:表示設定的閾值。

        ?比如我們選取子元素中 div 的個數為 2 的 a 元素:

        //a[count(div)=2] 

        text()

        text() 函數用于獲取元素的直接文本內容。一般與 contains() 結合使用,來選取文本內容包含指定字符串的元素。

        比如查找文本中包含 "熱烈歡迎" 的 div 元素。

        //div[contains(text(), "熱烈歡迎")]

        也可以用文本的精確匹配。

        //div[text()="熱烈歡迎"]

        node()

        node()?函數用于選取所有節點。其語法格式如下:

        //node()
        

          node()函數的功能與?* 通配符號類似,用于選取所有節點。例如:

          //* 
          或 
          //node()
          

            上述兩種表達式的效果相同,均用于選取頁面中的所有節點(但通配符 * 不包括文本,注釋,指令等節點,如果也要包含這些節點請用 node() 函數)。

            XPath 基礎語法

            路徑操作符

            操作符描述示例
            /從根節點選取元素/html/body
            //遞歸步進下降選擇文檔中符合條件的所有元素//a
            .選取當前節點./div
            ..選取當前節點的父節點../
            @選取屬性//div[@id]
            *通配符,選擇任意元素//*

            條件謂詞

            XPath 允許我們使用方括號?[]?來添加條件謂詞進行篩選限定 。

            //div[1]                                # 第一個div元素
            //div[last()]                           # 最后一個div元素
            //div[position()<3]                     # 前兩個div元素
            //div[@class]                           # 所有有class屬性的div元素
            //div[@class='main']                    # class屬性值為'main'的div元素
            //div[contains(@class, 'content')]      # class屬性包含'content'的div元素
            //a[text()='click']                     # 文本內容為'click'的a元素
            //a[count(div)=2]                       # 包含2個div元素的a元素

            軸操作

            以?百度熱搜?首頁為例。

            ancestor

            ancestor 用以獲取元素的祖先節點。比如 熱搜 對應? xpath 為:

            //div[2]/a/span[text()="熱搜"]

            則下面的 xpath 用以獲取 熱搜 元素對應的所有祖先節點:

            //div[2]/a/span[text()="熱搜"]/ancestor::*

            包含當前節點自身則需要用?ancestor-or-self:?

            //div[2]/a/span[text()="熱搜"]/ancestor-or-self::*

            則下面的 xpath 用以獲取 熱搜 元素對應的所有 div 祖先節點:

            //div[2]/a/span[text()="熱搜"]/ancestor::div

            descendant

            descendant 用以獲取元素的后代節點。

            比如獲取?//div[@id="sanRoot"] 的所有后代 div 節點(不限定節點類型則使用 *)

            //div[@id="sanRoot"]/descendant::div

            包含當前節點自身則需要用?decendant-or-self:?

            //div[@id="sanRoot"]/descendant-or-self::div

            following

            following 用以選取文檔中當前節點結束標簽之后的所有節點。

            //div/div[@class="bg-wrapper"]/following::*

            如果只選取當前節點之后的所有兄弟節點,則使用?following-sibling。

            //div/div[@class="bg-wrapper"]/following-sibling::*

            preceding

            preceding?用于選取文檔中當前節點開始標簽之前的所有節點(不包含當前節點的父輩節點)。

            //div[last()]/div[@class="content_1YWBm"]/preceding::*

            如果選取當前節點之前的所有同級節點,則使用?preceding-sibling。

            //div[last()]/div[@class="content_1YWBm"]/preceding-sibling::*

            parent

            parent 用以獲取元素的父節點。

            //div/div[@class="bg-wrapper"]/parent::*

            child

            child 用以獲取元素的子節點。

            //div/div[@id="sanRoot"]/child::*

            self?

            self 用以獲取當前元素節點自己本身。

            //div/div[@id="sanRoot"]/self::*

            attribute?

            通過屬性來獲取元素。

            比如獲取所有包含 class 屬性的節點。

            //attribute::class
            或
            //@class

            獲取所有包含 class 屬性的 div 節點。

             //div[@class]

            邏輯運算符

            and

            邏輯與,比如查詢熱搜的前三個熱搜。

            //div/div[@class="category-wrap_iQLoo horizontal_1eKyQ" and position()<4]

            or

            邏輯或

            //div/div[@class="category-wrap_iQLoo horizontal_1eKyQ" or position()=last()]

            not

            //div/a/div[not(@class="c-single-text-ellipsis")]

            XPath 優化

            一般可以在瀏覽器中直接復制?XPath,但是瀏覽器復制的 XPath 一般是用絕對路徑寫的能唯一定位這個元素的 XPath。 如果頁面結構稍微發生變動,可能導致 XPath 不可用。

            比如復制的 XPath 如下:

            //*[@id="sanRoot"]/main/div[2]/div/div[2]/div[1]/div[2]/a/div[1]

            優化后可以為:?

            //div[1]/div/a/div[@class="c-single-text-ellipsis"]

            ?XPath 常用的優化思路包括:

            • 找到元素附近的獨特標識(如 id、特定的 class 等)
            • 盡量使用相對路徑而非絕對路徑
            • 使用?contains()?等函數處理動態變化的屬性值

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

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

            相關文章

            聊聊自動化辦公未來趨勢

            1. 自動化辦公未來趨勢 1.1 智能化與AI融合加深 隨著人工智能技術的不斷成熟&#xff0c;其在自動化辦公中的應用將更加廣泛和深入。未來&#xff0c;辦公軟件將具備更強的智能交互能力&#xff0c;能夠理解自然語言指令&#xff0c;自動完成復雜的任務&#xff0c;如文檔編輯…

            智慧工會服務平臺建設方案Word(23頁)

            1. 引言 隨著信息技術的快速發展&#xff0c;傳統工會服務模式面臨挑戰&#xff0c;智慧工會服務平臺應運而生。該平臺旨在通過數字化手段&#xff0c;整合工會資源&#xff0c;優化服務流程&#xff0c;提高工作效率&#xff0c;為會員提供更加便捷、高效、個性化的服務體驗。…

            React Hooks 深入淺出

            目錄 引言&#xff1a;React Hooks 的革命基礎 Hooks useState&#xff1a;狀態管理的新方式useEffect&#xff1a;組件生命周期的替代方案useContext&#xff1a;簡化 Context API 額外的 Hooks useReducer&#xff1a;復雜狀態邏輯的管理useCallback 與 useMemo&#xff1a;…

            【應急響應】- 日志流量如何分析?

            【應急響應】- 日志流量如何下手&#xff1f;https://mp.weixin.qq.com/s/dKl8ZLZ0wjuqUezKo4eUSQ

            stm32 debug卡在0x1FFFxxxx

            自己畫的一個四軸飛機電路板&#xff0c;之前還能debug&#xff0c;改了一下mos管兩端的電阻&#xff0c;還能正常下載&#xff0c;藍牙接收也正常&#xff0c;但是debug出問題了&#xff0c;剛下載就自動運行&#xff0c;然后程序就在0x1FFFxxxx附近循環運行&#xff0c;這一塊…

            java-----------------多態

            多態&#xff0c;當前指的是 java 所呈現出來的一個對象 多態 定義 多態是指同一個行為具有多個不同表現形式或形態的能力。在面向對象編程中&#xff0c;多態通過方法重載和方法重寫來實現。 強弱類型語言 javascript 或者python 是弱類型語言 C 語言&#xff0c;或者 C…

            Java 23種設計模式 - 結構型模式7種

            Java 23種設計模式 - 結構型模式7種 1 適配器模式 適配器模式把一個類的接口變換成客戶端所期待的另一種接口&#xff0c;從而使原本因接口不匹配而無法在一起工作的兩個類能夠在一起工作。 優點 將目標類和適配者類解耦增加了類的透明性和復用性&#xff0c;將具體的實現封…

            Git clone時出現SSL certificate problem unable to get local issuer certificate

            正確解決方法 git config --global http.sslVerify false錯誤解決方法&#xff1a;&#xff08;主要是看錯了嘿嘿&#xff0c;但是如果是 OpenSSL SSL_read: Connection was reset, errno 10054 Failed to connect to github.com port 443: Timed out 原…

            DevExpressWinForms-AlertControl-使用教程

            文章目錄 AlertControl-使用教程一、將 AlertControl 添加到 Form二、編輯 AlertControl 的 HtmlTemplateHTML Template Editor介紹編輯HTML Template 三、使用AlertControl彈出AlertAlert中的按鈕事件獲取 Alert 標題等信息向Alert傳遞參數 總結源碼 AlertControl-使用教程 一…

            制作項目進度表常用的 8 款項目管理工具分享

            在數字化管理和高效協作的今天&#xff0c;項目進度表軟件已經成為企業管理不可或缺的工具。無論是中小型企業還是大型機構&#xff0c;都需要通過精準的項目計劃和實時的進度跟蹤來確保業務目標的順利達成。這篇文章將聚焦項目進度表軟件&#xff0c;深入探討市場上8款主流產品…

            SecureCRT網絡穿透/代理

            場景 公司的辦公VPN軟件只有Windows系統版本&#xff0c;沒有Macos系統版本&#xff0c;而日常開發過程中需要先登錄VPN后&#xff0c;然后才能登錄應用服務器。 目的&#xff1a;Macos系統在使用SecureCRT時&#xff0c;登錄服務器&#xff0c;需要走Parallels Desktop進行網絡…

            【計算機網絡-傳輸層】傳輸層協議-TCP核心機制與可靠性保障

            &#x1f4da; 博主的專欄 &#x1f427; Linux | &#x1f5a5;? C | &#x1f4ca; 數據結構 | &#x1f4a1;C 算法 | &#x1f152; C 語言 | &#x1f310; 計算機網絡 上篇文章&#xff1a;傳輸層協議-UDP 下篇文章&#xff1a; 網絡層 我們的講解順序是&…

            OpenMagnetic的介紹與使用

            1. Background OM&#xff08;OpenMagnetic&#xff09;OpenMagnetics&#xff0c;能涵蓋氣隙磁阻&#xff0c;磁導率&#xff0c;鐵芯損耗、磁滯損耗、渦流電流損耗、渦流效應、漏感、溫升的計算與仿真[1]。 鐵損計算模型&#xff1a;改進的Steinmetz方程[2] 氣隙阻抗計算&…

            【JVM】從零開始深度解析JVM

            本篇博客給大家帶來的是JVM的知識點, 重點在類加載和垃圾回收機制上. &#x1f40e;文章專欄: JavaEE初階 &#x1f680;若有問題 評論區見 ? 歡迎大家點贊 評論 收藏 分享 如果你不知道分享給誰,那就分享給薯條. 你們的支持是我不斷創作的動力 . 王子,公主請閱&#x1f680; …

            字符串---Spring字符串基本處理

            一、String類的特性 不可變性 String對象一旦創建&#xff0c;內容不可更改&#xff0c;任何修改操作都會生成新對象。字符串常量池 字符串字面量&#xff08;如"abc"&#xff09;直接存儲在常量池中&#xff0c;重復字面量共享同一內存地址。創建方式 雖然都是字符…

            26考研——中央處理器_CPU 的功能和基本結構(5)

            408答疑 文章目錄 一、CPU 的功能和基本結構CPU 的功能CPU 的基本結構運算器控制器 CPU 的寄存器運算器中的寄存器控制器中的寄存器 八、參考資料鮑魚科技課件26王道考研書 九、總結 一、CPU 的功能和基本結構 CPU 的功能 中央處理器&#xff08;CPU&#xff09;由運算器和控…

            傳統數據展示 vs 可視化:誰更打動人心?

            數據&#xff0c;每天都在我們身邊流動&#xff1a;從你手機里的健康步數&#xff0c;到企業財報中的營收增長&#xff0c;再到國家發布的經濟指標。但問題是——你怎么“看”這些數據&#xff1f; 過去&#xff0c;我們習慣用表格、文字和報告來展示數據&#xff0c;這種方式…

            Base64 編碼原理詳細解析

            Base64 編碼是一種常見的數據編碼方式&#xff0c;它將二進制數據轉化為可打印的 ASCII 字符串。Base64 編碼廣泛應用于電子郵件、URL 編碼、HTTP 請求和響應中等場景。它的核心作用是讓二進制數據可以通過僅支持文本的協議或媒介進行傳輸。本文將更深入地探討 Base64 編碼的原…

            一周學會Pandas2 Python數據處理與分析-Pandas2數據排序操作

            鋒哥原創的Pandas2 Python數據處理與分析 視頻教程&#xff1a; 2025版 Pandas2 Python數據處理與分析 視頻教程(無廢話版) 玩命更新中~_嗶哩嗶哩_bilibili Pandas 2提供了多種靈活的數據排序方法&#xff0c;主要針對 DataFrame 和 Series 對象。 1. 按值排序&#xff1a;s…

            計算機二級(C語言)已過

            非線性結構&#xff1a;樹、圖 鏈表和隊列的結構特性不一樣&#xff0c;鏈表可以在任何位置插入、刪除&#xff0c;而隊列只能在隊尾入隊、隊頭出隊 對長度為n的線性表排序、在最壞情況下時間復雜度&#xff0c;二分查找為O(log2n)&#xff0c;順序查找為O(n)&#xff0c;哈希查…