學會XPath,輕鬆抓取網頁資料

2023-11-30 12:01:47

一、定義

XPath(XML Path Language)是一種用於在 XML 檔案中定位和選擇節點的語言。XPath的選擇功能非常強大,可以通過簡單的路徑選擇語法,選取檔案中的任意節點或節點集。學會XPath,可以輕鬆抓取網頁資料,提高資料獲取效率。

二、XPath基礎語法

節點(Nodes): XML 檔案的基本構建塊,可以是元素、屬性、文字等。
路徑表示式: 用於定位 XML 檔案中的節點。路徑表示式由一系列步驟組成,每個步驟用斜槓 / 分隔。

XPath的節點是指在XML或HTML檔案中被選擇的元素或屬性。XPath中有7種型別的節點,包括元素節點、屬性節點、文位元組點、名稱空間節點、處理指令節點、註釋節點以及檔案節點(或稱為根節點)。

- 元素節點:表示XML或HTML檔案中的元素。例如,在HTML檔案中,<body>、<div>、<p>等都是元素節點。在XPath中,可以使用元素名稱來選擇元素節點,例如://div表示選擇所有的<div>元素。

- 屬性節點:表示XML或HTML檔案中元素的屬性。例如,在HTML檔案中,元素的class、id、src等屬性都是屬性節點。在XPath中,可以使用@符號來選擇屬性節點,例如://img/@src表示選擇所有<img>元素的src屬性。

- 文位元組點:表示XML或HTML檔案中的文字內容。例如,在HTML檔案中,<p>標籤中的文字內容就是文位元組點。在XPath中,可以使用text()函數來選擇文位元組點,例如://p/text()表示選擇所有<p>元素中的文字內容。

- 名稱空間節點:表示XML檔案中的名稱空間。名稱空間是一種避免元素命名衝突的方法。在XPath中,可以使用namespace軸來選擇名稱空間節點,例如://namespace::*表示選擇所有的名稱空間節點。

- 處理指令節點:表示XML檔案中的處理指令。處理指令是一種用來給處理器傳遞指令的機制。在XPath中,可以使用processing-instruction()函數來選擇處理指令節點,例如://processing-instruction('xml-stylesheet')表示選擇所有的xml-stylesheet處理指令節點。

- 註釋節點:表示XML或HTML檔案中的註釋。註釋是一種用來新增說明和備註的機制。在XPath中,可以使用comment()函數來選擇註釋節點,例如://comment()表示選擇所有的註釋節點。

- 檔案節點:表示整個XML或HTML檔案。檔案節點也被稱為根節點。在XPath中,可以使用/符號來選擇檔案節點,例如:/表示選擇整個檔案節點。

本文使用XML範例如下

<bookstore>
    <book category='fiction'>
        <title>活著</title>
        <author>餘華</author>
        <press>作家出版社</press>
        <date>2012-8-1</date>
        <page>191</page>
        <price>20.00</price>
        <staple>平裝</staple>
        <series>餘華作品(2012版)</series>
        <isbn>9787506365437</isbn>
    </book>
    <book category='non-fiction'>
        <title>撒哈拉的故事</title>
        <author>三毛</author>
        <press>哈爾濱出版社</press>
        <date>2003-8</date>
        <page>217</page>
        <price>15.80</price>
        <staple>平裝</staple>
        <series>三毛全集(華文天下2003版)</series>
        <isbn>9787806398791</isbn>
    </book>
    <book category='non-fiction'>
        <title>明朝那些事兒(1-9)</title>
        <author>當年明月</author>
        <press>中國海關出版社</press>
        <date>2009-4</date>
        <page>2682</page>
        <price>358.20</price>
        <staple>精裝16開</staple>
        <series>明朝那些事兒(典藏本)</series>
        <isbn>9787801656087</isbn>
    </book>
</bookstore>

除了這些基本節點型別之外,XPath還支援使用萬用字元:

萬用字元 描述 範例
* 匹配任何元素節點 //book/* 選取<book>元素下的任意子元素節點
@* 匹配任何屬性節點 //book/@* 選取<book>元素上的任意屬性節點,如<book category='fiction'>中的category屬性
node() 匹配任何型別的節點 //book/node() 選取<book>元素下的所有型別的子節點,包括元素節點、文位元組點、註釋節點等

以及使用謂詞來進一步篩選選擇的節點集。謂詞是一種用來對節點進行過濾和排序的機制,可以包含比較運運算元、邏輯運運算元和函數等,部分範例如下:

謂語 描述 範例
[position()=n] 選取位於指定位置的節點。n 是節點的位置(從 1 開始計數) //book[position()=1] 選取第一個<book>元素
[last()=n] 選取位於指定位置的最後一個節點。n 是節點的位置(從 1 開始計數) //book[last()=1] 選取最後一個<book>元素
[contains(string, substring)] 選取包含指定子字串的節點。string 是節點的文字內容,substring 是要查詢的子字串 //book[contains(title, 'XML')] 選取標題中包含子字串'XML'<book>元素
[starts-with(string, prefix)] 選取以指定字首開始的節點。string 是節點的文字內容,prefix 是要匹配的字首字串 //book[starts-with(title, 'The')] 選取標題以'The'開始的<book>元素
[text()=string] 選取文字內容完全匹配的節點。string 是要匹配的文字內容 //book[text()='Book Title'] 選取文字內容為'Book Title'<book>元素
[@category='non-fiction'] 選取具有指定屬性值的節點。category 是屬性名稱,non-fiction 是要匹配的值 //book[@category='non-fiction'] 選取具有屬性category值為'non-fiction'<book>元素

XPath使用路徑表示式來選取XML或HTML檔案中的節點或節點集。下面是一些常用的路徑表示式:

表示式 描述 範例
nodename 選取此節點的所有子節點 //bookstore/book 選取<bookstore>元素下所有<book>子元素
/ 從根節點選取直接子節點 /bookstore 從根節點選取<bookstore>元素
// 從當前節點選取子孫節點 //book 選取所有<book>元素,無論它們在檔案中的位置
. 選取當前節點 ./title 選取當前節點的<title>子元素
.. 選取當前節點的父節點 ../price 選取當前節點的父節點的<price>子元素
@ 選取屬性 //book/@id 選取所有<book>元素的id屬性

三、XPath使用範例

選擇所有名稱為title的節點://title
選擇所有名稱為title,同時屬性lang的值為eng的節點://title[@lang='eng']
選擇id為bookstore的節點的所有子節點:/bookstore/*
選擇id為bookstore的節點的所有子孫節點:/bookstore//*
選擇id為bookstore的節點的直接子節點中的第一個節點:/bookstore/*[1]
選擇id為bookstore的節點的屬性為category的值:/bookstore/@category

四、XPath的高階用法

XPath語言提供了一些高階的功能,包括:

軸(Axes):XPath提供了幾種軸,用於在檔案中導航。包括child(子元素)、ancestor(祖先元素)、descendant(後代元素)和following-sibling(後續同級元素)等。

函數:XPath提供了一些內建的函數,如count(),concat(),string(),local-name(),contains(),not(),string-length()等,可以用於處理和操作節點和屬性3。

條件語句:XPath提供了條件語句(如if-else語句),使得我們可以根據某些條件來選擇性地提取元素或屬性3。

五、.NET中使用

// XML 檔案內容
string xmlContent = @"
            <bookstore>
                <book category='fiction'>
                    <title>活著</title>
                    <author>餘華</author>
                    <press>作家出版社</press>
                    <date>2012-8-1</date>
                    <page>191</page>
                    <price>20.00</price>
                    <staple>平裝</staple>
                    <series>餘華作品(2012版)</series>
                    <isbn>9787506365437</isbn>
                </book>
                <book category='non-fiction'>
                    <title>撒哈拉的故事</title>
                    <author>三毛</author>
                    <press>哈爾濱出版社</press>
                    <date>2003-8</date>
                    <page>217</page>
                    <price>15.80</price>
                    <staple>平裝</staple>
                    <series>三毛全集(華文天下2003版)</series>
                    <isbn>9787806398791</isbn>
                </book>
                <book category='non-fiction'>
                    <title>明朝那些事兒(1-9)</title>
                    <author>當年明月</author>
                    <press>中國海關出版社</press>
                    <date>2009-4</date>
                    <page>2682</page>
                    <price>358.20</price>
                    <staple>精裝16開</staple>
                    <series>明朝那些事兒(典藏本)</series>
                    <isbn>9787801656087</isbn>
                </book>
            </bookstore>";

// 建立 XPath 檔案
using (XmlReader reader = XmlReader.Create(new StringReader(xmlContent)))
{
    XPathDocument xpathDoc = new XPathDocument(reader);

    // 建立 XPath 導航器
    XPathNavigator navigator = xpathDoc.CreateNavigator();

    // 使用 XPath 查詢(選擇所有位於bookstore下、其category屬性值為'fiction'的book元素中的title元素)
    string xpathExpression = "//bookstore/book[@category='fiction']/title";
    XPathNodeIterator nodes = navigator.Select(xpathExpression);

    // 檢查是否有匹配的節點
    if (nodes != null)
    {
        // 遍歷結果
        while (nodes.MoveNext())
        {
            // 檢查當前節點是否為空
            if (nodes.Current != null)
            {
                Console.WriteLine(nodes.Current.Value);
            }
        }
    }
}

執行結果

六、XPath在自動化測試中的應用

XPath最常用的場景之一就是在自動化測試中用來選擇HTML DOM節點。例如,在Selenium自動化測試中,可以使用XPath作為選擇web元素的主要方法之一。通過XPath選擇器,可以方便地定位頁面中的任意元素,進行自動化測試操作。

七、XPath的優勢與不足

XPath的優勢在於其強大的選擇功能,可以通過簡單的路徑選擇語法,選取檔案中的任意節點或節點集。此外,XPath還支援超過100個內建函數,可用於字串處理、數值計算、日期和時間比較等等。這些函數可以大大提高資料處理的效率。

然而,XPath也有其不足之處。首先,XPath對於複雜的檔案結構可能會變得非常複雜,導致選擇語句難以理解和維護。其次,XPath在處理大量資料時可能會出現效能問題,因為它需要遍歷整個檔案來查詢匹配的節點。因此,在使用XPath時需要注意優化查詢語句,提高查詢效率。

八、總結

學會XPath,可以輕鬆抓取網頁資料,提高資料獲取效率。本文介紹了XPath的定義、基礎語法、使用範例、高階用法、.NET中使用舉例以及在自動化測試中的應用場景,同時也討論了XPath的優勢與不足。希望本文能夠幫助讀者更好地理解和掌握XPath的使用方法。

希望以上內容能夠幫助你理解和學習XPath。歡迎點贊、關注、收藏,如果你還有其他問題,歡迎評論區交流。