c# 使用HtmlAgilityPack解析Html
HtmlAgilityPack 是一個開源的快速解析Html的C#類庫。簡單理解,它可以像解析Xml一樣,將Html根據(jù)XPATH轉(zhuǎn)化為一個個Node節(jié)點,并支持調(diào)整節(jié)點以及節(jié)點的各種屬性。
多種方式加載Html
主要加載方式有3類:從網(wǎng)絡(luò)鏈接加載、從字符串文本中加載、從文件加載
var doc = new HtmlDocument();
//直接通過url加載
doc = new HtmlWeb().Load("https://www.baidu.com/");
//通過字符串加載
doc.LoadHtml(result);
//通過html文件加載 可指定編碼方式
doc.Load(@"c://index.html",Encoding.UTF8)
HtmlNode常用方法
使用SelectNodes()和SelectSingleNode()方法(類似解析XML格式數(shù)據(jù)的XmlDocument)來獲取的目標節(jié)點,分別對應(yīng)HtmlNodeCollection和HtmlNode兩個類。
"http://"表示從根節(jié)點開始查找,兩個斜杠"http://"表示查找所有childnodes;一個斜杠"/"表示只查找第一層的childnodes(即不查找grandchild);點斜杠"./"表示從當前結(jié)點而不是根結(jié)點開始查找(只在xpath最開始出現(xiàn))
注意:
id class 屬性匹配大小寫敏感
xpath匹配下標從1開始
1. 通過屬性和路徑匹配來選擇對應(yīng)的節(jié)點
var node = doc.DocumentNode;
//選擇不包含class屬性的div節(jié)點
var result = node.SelectNodes(".//div[not(@class)]");
//選擇不包含class和id屬性的div節(jié)點
var result = node.SelectNodes(".//div[not(@class) and not(@id)]");
//選擇class中包含"expire"的span節(jié)點
var result = node.SelectNodes(".//span[contains(@class,'expire')]");
//選擇class中不包含"expire"的span節(jié)點
var result = node.SelectNodes(".//span[not(contains(@class,'expire'))]");
//選擇class="expire"的span節(jié)點
var result = node.SelectNodes(".//span[@class='expire']");
//選擇id="expire"的div節(jié)點下第一個div節(jié)點
var result = node.SelectSingleNode(".//div[@id='expire']/div[1]");
2. 獲取節(jié)點文本內(nèi)容
根據(jù)需求不同,通過不同的方式來獲取相應(yīng)的文本內(nèi)容。
OuterHtml:返回包含當前節(jié)點在內(nèi)的所有Html
InnerHtml:返回當前節(jié)點內(nèi)所有子節(jié)點Html
InnerText:返回當前節(jié)點內(nèi)去除所有Html后的文本內(nèi)容
<div id="title"> <p> <a class="MainTitle" rel="external nofollow" rel="external nofollow" rel="external nofollow" >傅小灰</a> </p> </div>
以上面的Html為例
var node= doc.DocumentNode.SelectSingleNode("http://div[@id='title'/p]");
node.OuterHtml; //返回結(jié)果:<p><a class="MainTitle" rel="external nofollow" rel="external nofollow" rel="external nofollow" >傅小灰</a></p>
node.InnerHtml; //返回結(jié)果:<a class="MainTitle" rel="external nofollow" rel="external nofollow" rel="external nofollow" >傅小灰</a>
node.InnerText; //返回結(jié)果:傅小灰
3. 獲取/修改節(jié)點屬性值
以上面的Html舉例,我們獲取到了a標簽為node節(jié)點。我們想要獲取a標簽指向的鏈接地址,并修改為我們設(shè)定的地址。這里以href屬性舉例,同樣可以用在class/src/id等屬性上。
var node= doc.DocumentNode.SelectSingleNode("http://div[@id='title'/p/a]");
//第二個參數(shù)為找不到對應(yīng)屬性時返回的默認值
var url = node.GetAttributeValue("href", "");//返回結(jié)果:https://www.cnblogs.com/cplemom/
//設(shè)置屬性值
node.SetAttributeValue("href", "http://www.cplemom.com/");
//獲取所有屬性值
var list = node.Attributes.ToList();
4. 刪除/替換節(jié)點
繼續(xù)以上面的Html舉例,我們獲取到了a標簽為node節(jié)點。
對于我們不需要的內(nèi)容,我們只需要調(diào)用節(jié)點Remove方法即可。
var node= doc.DocumentNode.SelectSingleNode("http://div[@id='title'/p/a]");
node.Remove();//刪除節(jié)點
一個很常見的場景就是我們需要移除a標簽,但是要在html上下文中保留a標簽的文本。
PS : a標簽內(nèi)的文本在HtmlDocument中其實是一個text類型的node節(jié)點。所以我們可以通過刪除a標簽,保留text標簽的方式來完成目標。
node.ParentNode.RemoveChild(node,true);
true表示留下a標簽的子節(jié)點只刪除a標簽,在這里就表示保留下“傅小灰”text節(jié)點; false表示將此結(jié)點連同所有子節(jié)點一起刪除。
換個角度思考下,當前node節(jié)點代表的是單個a標簽,那么如果p標簽下存在多個a標簽需要處理,或者node節(jié)點指向的就是p標簽?zāi)??當然,我們可以通過獲取所有a標簽然后循環(huán)處理的方式來實現(xiàn),但是還有沒有別的更好的處理方式呢?
這里提供一個思路,獲取所有的文本內(nèi)容,新建為一個text節(jié)點,然后替換掉當前節(jié)點。
node.ParentNode.ReplaceChild(HtmlNode.CreateNode(item.InnerText), node);
幾個常見使用場景和解決方案
1. 獲取所有的img標簽
//通過Descendants獲取所有的子后代節(jié)點中的img標簽
var list = node.Descendants("img");
//通過Xpath匹配獲取所有img標簽
var list = node.SelectNodes("http://img");
2. 通過url訪問時需要攜帶cookie等驗證信息
有些頁面需要攜帶驗證信息才能訪問,比如用戶中心,訂單列表等,這時候直接通過HtmlWeb類獲取html會被拒絕。有個簡單的方式就是通過HttpClient請求到對應(yīng)的html內(nèi)容,再使用HtmlDocument加載。其實HtmlWeb說白了也是封裝的HttpWebRequest進行網(wǎng)絡(luò)請求的,所以暴露一個委托給外部用以修改請求上下文。
var web = new HtmlWeb();
web.PreRequest = new HtmlWeb.PreRequestHandler(GetRequest);
var node = web.Load("https://www.cplemom.com/");
public static bool GetRequest(HttpWebRequest req)
{
req.Headers.Add("Host", "www.cplemom.com");
req.Headers.Add("Cookie", "xxxxxxxxxxxxx");
return true;
}
總結(jié)
用到現(xiàn)在,個人感覺上面的方法已經(jīng)可以實現(xiàn)90%以上的的Html解析相關(guān)需求了,更多方便快捷的方法還是到官網(wǎng)的API文檔進行了解吧。
以上就是c# 使用HtmlAgilityPack解析Html的詳細內(nèi)容,更多關(guān)于c# HtmlAgilityPack解析Html的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Unity游戲開發(fā)中的中介者模式的應(yīng)用與實現(xiàn)
中介者模式是Unity游戲開發(fā)中常用的設(shè)計模式之一,用于減少對象之間的直接耦合,通過引入中介者來協(xié)調(diào)對象之間的交互。通過中介者模式,游戲?qū)ο罂梢愿屿`活地進行交互和協(xié)同工作,降低系統(tǒng)復雜度,使代碼更加易于維護和擴展2023-05-05
C#控制Excel Sheet使其自適應(yīng)頁寬與列寬的方法
這篇文章主要介紹了C#控制Excel Sheet使其自適應(yīng)頁寬與列寬的方法,涉及C#操作Excel的相關(guān)技巧,具有一定參考借鑒價值,需要的朋友可以參考下2016-06-06
C#實現(xiàn)多種圖片格式轉(zhuǎn)換的示例詳解
這篇文章主要為大家詳細介紹了C#如何實現(xiàn)多種圖片格式轉(zhuǎn)換,例如轉(zhuǎn)換成圖標圖像ICO,文中的示例代碼講解詳細,感興趣的小伙伴可以跟隨小編一起學習一下2024-01-01
C#操作本地文件及保存文件到數(shù)據(jù)庫的基本方法總結(jié)
C#使用System.IO中的文件操作方法在Windows系統(tǒng)中處理本地文件相當順手,這里我們還總結(jié)了在Oracle中保存文件的方法,嗯,接下來就來看看整理的C#操作本地文件及保存文件到數(shù)據(jù)庫的基本方法總結(jié)2016-05-05
詳解C# 利用反射根據(jù)類名創(chuàng)建類的實例對象
這篇文章主要介紹了詳解C# 利用反射根據(jù)類名創(chuàng)建類的實例對象,“反射”其實就是利用程序集的元數(shù)據(jù)信息,感興趣的小伙伴們可以參考一下。2017-03-03

