天天看點

C# HTML解析工具HtmlAgilityPack使用簡介

一、說明,官方CodePlex位址:http://htmlagilitypack.codeplex.com/

Html Agility Pack 不算一個很複雜的類庫,但它的功能确不弱,為解析DOM已經提供了足夠強大的功能支援,可以跟jQuery操作DOM媲美:)

Html Agility Pack最常用的基礎類其實不多,對解析DOM來說,就隻有HtmlDocument和HtmlNode這兩個常用的類,還有一個 HtmlNodeCollection集合類。其中HtmlWeb類幫助擷取Web頁面很方面。

二、添加引用很簡單

Install-Package HtmlAgilityPack
           

HtmlDocument類

當然在解析DOM前需要加載html原始檔案或者html的字元串,HtmlDocument類封裝了支援此功能的方法,下面是加載html的方法介紹。

HtmlDocument類定義了多個重載的Load方法來實作以不同方式加載html,其實主要分為兩種,一種是從Stream中加載html,另外一種是從實體路徑加載html,分别見下面:

方法:public void Load(TextReader reader)

說明:從指定的 TextReader對象中加載Html

示例:

HtmlDcument doc  = new  HtmlDocument();

StreamReader sr  =  File.OpenText( " file path " );

doc.Load(sr);

基于上面方法,衍生出了幾個不同重載方法。

以指定的Stream對象為主的有:

(1)public void Load(Stream stream)    ///從指定的Stream對象中加載html;

(2)public void Load(Stream stream, bool detectEncodingFromByteOrderMarks)    ///指定是否從順序位元組流中解析編碼格式

(3)public void Load(Stream stream, Encoding encoding)    ///指定編碼格式

(4)public void Load(Stream stream, Encoding encoding, bool detectEncodingFromByteOrderMarks)

(5)public void Load(Stream stream, Encoding encoding, bool detectEncodingFromByteOrderMarks, int buffersize)

以指定的實體路徑為主的有:

 (1)public void Load(string path)

(2)public void Load(string path, bool detectEncodingFromByteOrderMarks)    ///指定是否從順序位元組流中解析編碼格式

(3)public void Load(string path, Encoding encoding)    ///指定編碼格式

(4)public void Load(string path, Encoding encoding, bool detectEncodingFromByteOrderMarks)

(5)public void Load(string path, Encoding encoding, bool detectEncodingFromByteOrderMarks, int buffersize)

HtmlDocument類中還定義了直接從html字元串中加載Html,如下:

方法:public void LoadHtml(string html)

說明:從指定的html字元串中加載html

示例:

HtmlDocument doc  = new  HtmlDocument();

string  html  = " <div id= " demo " ><span style= " color:red; " ><h1>Hello World!</h1></span></div> " ;

doc.LoadHtml(html);

 HtmlDocument類還有其他寫DOM方法的定義,這裡不作詳細介紹,留作以後專門介紹Html Agility Pack寫DOM章節介紹吧,這裡着重介紹Html Agility pack解析DOM的細節。

 HtmlNode類和HtmlNodeCollection類

通過HtmlDocument把html加載進來後,接着是要做什麼呢?當然是對html解析了,解析DOM就需要提到HtmlNode類 了。 HtmlDocument類由屬性DocumentNode屬性傳回目前Html解析後的一個全局的HtmlNode對象;如果想擷取某一個元素的 HtmlNode,可以通過HtmlDocument類的GetElementbyId(string Id)方法來擷取,傳回指定某一個html元素的HtmlNode對象。如何通過HtmlNode對象來通路DOM呢?介紹之前先對它的功能了解下。

HtmlNode類實作了IXPathNavigable接口,這說明了它可以通過xpath來查詢DOM了,如果對System.Xml 命名空間下的 XmlDocument類了解的,特别是使用過了SelectNodes()和SelectSingleNode()方法的朋友對使用HtmlNode類 将會很熟悉。其實Html Agility Pack内部是把html解析成xml文檔格式了的,是以支援xml中的一些常用查詢方式。下面對HtmlNode的一些主要的常用成員作簡要的說明。

 HtmlNode類的主要屬性

1)Attributes屬性

擷取目前Html元素的屬性的集合,傳回的是一個HtmlAttributeCollection對象。如一個div元素,它可能會定義一些屬性, 如:<div id="title" name="title" class="class-name" title="title div">***</div>,那Attributes傳回的HtmlAttributeCollection就包含了 “id,name,class,title”的資訊。HtmlAttributeCollection類是實作了接口 IList<HtmlAttribute>的一個集合類,故此可以通過下面代碼方式通路每一個成員。

HtmlNode node  =  doc.GetElementbyId( " title " );

string  titleValue  =  node.Attributes[ " title " ].Value;

或者

foreach (HtmlAttribute attr  in  node.Attributes)

{

Console.WriteLine( " {0}={1} " ,attr.Name,attr.Value);

} 在擷取屬性值時,如果某一個屬性名稱不存在的話,Attributes["name"]傳回的是null值。

2)FirstChild,LastChild,ChildNodes,ParentNode屬性

FirstChild屬性:傳回所有子節點的第一個節點,如下面代碼:

string  html  = " <div id= " demo " ><span style= " color:red; " ><h1>Hello World!</h1></span><div id= " innerDiv " >inner div</div></div> " ;

FirstChild則傳回的是“<span style="color:red;"><h1>Hello World!</h1></span>” 的節點。

LastChild屬性:傳回所有子節點的最後一個節點,以上面的html為例,則傳回“<div id="innerDiv">inner div</div>”節點。

ChildNodes屬性:傳回目前節點所有直接一代的子節點的集合,不包括跨代子節點,以上面的html為例,則傳回“<span style="color:red;"><h1>Hello World!</h1></span>” 和“<div id="innerDiv">inner div</div>”兩個節點。

ParentNode屬性:傳回目前節點的直接父節點。

3)擷取Html源碼和文本

HtmlNode類設計了OuterHtml屬性和InnerHtml屬性用于擷取目前節點的Html源碼。兩者不同之處 是,OuterHtml屬性傳回的是包含目前節點的Html代碼在内的所有Html代碼,而InnerHtml屬性傳回的是目前節點裡面子節點的所有 Html代碼。如下面:

HtmlDocument doc  = new  HtmlDocument();

string  html  = " <div id= " demo " ><span style= " color:red; " ><h1>Hello World!</h1></span></div> " ;

doc.LoadHtml(html);

HtmlNode node  =  doc.HtmlDocument;

Console.WriteLine(node.OuterHtml);  ///  return " <div id="demo"><span style="color:red;"><h1> Hello World! </h1></span></div> ";

Console.WriteLine(node.InnerHtml);  ///  return " <span style="color:red;"><h1> Hello World! </h1></span> ";

如要擷取節點的文本值,通過InnerText屬性來擷取,InnerText屬性過濾掉了所有的Html标記代碼,隻傳回文本值,如下面:

Console.WriteLine(node.InnerText); ///  return "Hello World!";

HtmlNode類的主要方法

HtmlNode類提供了足夠豐富的方法供查詢目前節點下的子節點(元素),當然也包括查詢目前節點的父節點(元素)的方法,下面列出主要的方法和使用說明。

擷取父節點的系列方法:

1)public IEnumerable<HtmlNode> Ancestors()

擷取目前節點的父節點清單(不包含自身)。

2)public IEnumerable<HtmlNode> Ancestors(string name)

以指定一個名稱來擷取父節點的清單(不包含自身)。

3)public IEnumerable<HtmlNode> AncestorsAndSelf()

擷取目前節點的父節點清單(包含自身)。

4)public IEnumerable<HtmlNode> AncestorsAndSelf(string name)

以指定一個名稱來擷取父節點的清單(包含自身)。

擷取子節點的系列方法:

1)public IEnumerable<HtmlNode> DescendantNodes()

擷取目前節點下的所有子節點的清單,包括子節點的子節點(不包含自身)。

2)public IEnumerable<HtmlNode> DescendantNodesAndSelf()

擷取目前節點下的所有子節點的清單,包括子節點的子節點(包含自身)。

3)public IEnumerable<HtmlNode> Descendants()

擷取目前節點下的直接子節點的清單(不包含自身)。

4)public IEnumerable<HtmlNode> DescendantsAndSelf()

擷取目前節點下的直接子節點的清單(包含自身)。

5)public IEnumerable<HtmlNode> Descendants(string name)

擷取目前節點下的以指定名稱的子節點清單。

6)public IEnumerable<HtmlNode> DescendantsAndSelf(string name)

擷取目前節點下的以指定名稱的子節點的清單(包含自身)。

7)public HtmlNode Element(string name)

擷取第一個符合指定名稱的直接子節點的節點元素。

8)public IEnumerable<HtmlNode> Elements(string name)

擷取符合指定名稱的所有直接子節點的節點清單。

9)public HtmlNodeCollection SelectNodes(string xpath)

擷取符合指定的xpath的子節點清單。

10)public HtmlNode SelectSingleNode(string xpath)

擷取符合指定的xpath的單個位元組點元素。

查詢節點的方法主要是上面10個方法,該類還有其他寫節點的系列方法,這裡不詳細介紹寫操作的方法,留作以後詳細介紹。

結合Xpath進行查詢節點是功能比較強大,這像操作xml那樣友善。