HtmlAgilityPack中使用xpath獲取屬性值

2022-07-26 18:00:32

HtmlAgilityPack介紹

HtmlAgilityPack是一個專門用來解析Html的庫,它可以使用xml的方式來解析html。


有人說了,html本身不就是xml?是的,html就是xml,但是html很寬鬆,沒有關閉的節點也可以用,還有一些其他的內容比如js夾雜在裡面。如果直接使用xml解析庫的話9成會報錯的。


而HtmlAgilityPack會去處理這些問題,把Html轉成一個接近標準的xml來供我們使用。

獲取內容

網上關於HtmlAgilityPack的介紹其實很多,而且用法其實就那麼幾句話。

var doc = new HtmlAgilityPack.HtmlDocument();
            doc.LoadHtml(html);
            var root = doc.DocumentNode;

這個也沒啥好說的,主要就是doc.LoadHtml(html);這裡有個過載是doc.Load(),裡面可以直接放url,也可以放Stream

我們這裡使用LoadHtml直接載入html內容主要是因為我們的html拿的時候可能還需要別的東西,需要另行獲取。


最後的var root = doc.DocumentNode;這個root就是<html>節點,整個html的根目錄。


然後很多文章的說法就是我們要獲取Node,即使用

var node =root.SelectSingleNode("xpath");

這樣肯定是沒問題的,然後我們如果要獲得它的屬性,就可以拿這個Node的node.GetAttributeValue("name", 預設值);獲取內容。


比如我們要獲取idtesta標籤的href,我們可以寫個例子

            var doc = new HtmlAgilityPack.HtmlDocument();
            doc.LoadHtml(html);
            var root = doc.DocumentNode;
            var node =root.SelectSingleNode("//a[@id='test']");
            var href = GetAttributeValue("href", ""); 

這樣我們就能獲取到href了。是不是很簡單?

直接獲取屬性值

上面的例子看起來很好,但是有個比較麻煩的問題,就是有時候我們想直接獲取屬性值。比如我有一個這樣的xpath //a[@id='test']/@href,如果我們還用上面的程式碼套進去。

            var doc = new HtmlAgilityPack.HtmlDocument();
            doc.LoadHtml(html);
            var root = doc.DocumentNode;
            var node =root.SelectSingleNode("//a[@id='test']/@href");

我們的node是不是就是href的值呢?經過測試,不是的,這裡的node還是那個a。


所以我們無法直接這樣來獲取。

經過一番查詢,發現HtmlAgilityPack提供了一個HtmlNodeNavigator來完成這個需求。

var doc = new HtmlAgilityPack.HtmlDocument();
            doc.LoadHtml(html);
            var root = doc.DocumentNode;
            HtmlNodeNavigator navigator = (HtmlNodeNavigator)root.CreateNavigator();
            var node = navigator.SelectSingleNode("//a[@id='test']/@href");
            var href = node.Value;

這裡我們可以獲取到一個HtmlNodeNavigator的node,這個node不是指向a標籤,而是直接指向href屬性,所以我們直接拿node.Value就可以獲取到真正的href的值了