C#使用HtmlAgilityPack組件解析html文檔
一、HtmlAgilityPack介紹
參考:
GitHub:https://github.com/zzzprojects/html-agility-pack/releases
官網:https://html-agility-pack.net/
https://www.nuget.org/packages/HtmlAgilityPack/
HtmlAgilityPack(以下簡稱HAP)是一個基於.Net的、第三方免費開源的微型類庫,主要用於在服務器端解析html文檔。
HtmlAgilityPack為網頁提供瞭標準的DOM API和XPath導航 。使用WebBrowser和HttpWebRequest下載的網頁可以用Html Agility Pack來解析。
Xpath表達式的參考文檔可見:XML基本概念XPath、XSLT與XQuery函數介紹
二、屬性和方法
HtmlAgilityPack中的HtmlNode類與XmlNode類差不多,HtmlDocument類與XmlDocument類差不多。
參考:C#下使用XmlDocument操作XML
1、屬性:
- OwnerDocument:節點所在的HtmlDocument文檔
- Attributes: 獲取節點的屬性集合
- ParentNode:獲取該節點的父節點
- ChildNodes:獲取子節點集合(包括文本節點)
- FirstChild: 獲取第一個子節點
- LastChild: 獲取最後一個子節點
- Id: 獲取該節點的Id屬性
- Name:Html元素名
- NodeType: 獲取該節點的節點類型
- InnerHtml: 獲取該節點的Html代碼
- InnerText: 獲取該節點的內容,與InnerHtml不同的地方在於它會過濾掉Html代碼,而InnerHtml是連Html代碼一起輸出
- OuterHtml: 整個節點的代碼
- PreviousSibling: 獲取前一個兄弟節點
- NextSibling: 獲取下一個兄弟節點
- HasAttributes :判斷該節點是否含有屬性
- HasChildNodes: 判斷該節點是否含有子節點
- HasClosingAttributes : 判斷該節點的關閉標簽是否含有屬性(</xxx class="xxx">)
- Closed:該節點是否已關閉(</xxx>)
- ClosingAttributes在關閉標簽的屬性集合StreamPosition: 該節點位於整個Html文檔的字符位置
- XPath: 根據節點返回該節點的XPath
2、方法:
- Load (string path): 從路徑中加載一個文檔
- SelectNodes (string xpath): 根據XPath獲取一個節點集合
- SelectSingleNode (string xpath): 根據XPath獲取唯一的一個節
- Ancestors (): 返回此元素的所有上級節點的集合。
- DescendantNodes (): 獲取所有子代節點
- Element (string name): 根據參數名獲取一個元素
- Elements (string name): 根據參數名獲取匹配的元素集合
- GetAttributeValue(string name, bool def): 幫助方法,用來獲取此節點的屬性的值(佈爾類型)。如果未找到該屬性,則將返回默認值。
- ChildAttributes(string name): 獲取所有子元素的屬性(參數名要與元素名匹配)
- IsEmptyElement(string name): 確定是否一個空的元素節點。
- IsOverlappedClosingElement(string text): 確定是否文本對應於一個節點可以保留重疊的結束標記。
- AppendChild(HtmlNode newChild): 將參數元素追加到為調用元素的子元素(追加在最後)
- PrependChild(HtmlNode newChild): 將參數中的元素作為子元素,放在調用元素的最前面
- Clone(): 本節點克隆到一個新的節點
- CopyFrom(HtmlNode node): 創建重復的節點和其下的子樹。
- CreateNavigator(): 返回的一個對於此文檔的XPathNavigator
- CreateNode(string html): 靜態方法,允許用字符串創建一個新節點
- CreateRootNavigator(): 創建一個根路徑的XPathNavigator
- InsertAfter(HtmlNode newChild, HtmlNode refChild): 將一個節點插入到第二個參數節點的後面,與第二個參數是兄弟關系
- InsertBefore(HtmlNode newChild, HtmlNode refChild): 將一個節點插入到第二個參數節點的後面,與第二個參數是兄弟關系
- Remove(): 從父集合中移除調用節點
- SetAttributeValue(string name, string value): 設置調用節點的屬性
- WriteContentTo(): 將該節點的所有子級都保存到一個字符串中。
- WriteTo(): 將當前節點保存到一個字符串中。
- Save(string filename): 將HTML文檔保存到指定的路徑
三、用法舉例
下面是幾個簡單使用說明:
1、獲取網頁title:
doc.DocumentNode.SelectSingleNode("//title").InnerText;//XPath中:“//title”表示所有title節點。SelectSingleNode用於獲取滿足條件的唯一的節點。
2、獲取所有的超鏈接:
doc.DocumentNode.Descendants("a")
3、獲取name為kw的input,也就是相當於getElementsByName():
var kwBox = doc.DocumentNode.SelectSingleNode("//input[@name='kw']");
示例:
private void Form1_Load(object sender, EventArgs e) { List<Result> list = new List<Result>(); HtmlWeb htmlWeb = new HtmlWeb(); htmlWeb.OverrideEncoding = Encoding.UTF8;//編碼,這裡網上有些很多寫法都不正確 HtmlAgilityPack.HtmlDocument htmlDoc = htmlWeb.Load(@http://www.cnblogs.com/); //選擇博客園首頁文章列表 htmlDoc.DocumentNode.SelectNodes("//div[@id='post_list']/div[@class='post_item']").//雙斜杠“//”表示從跟節點開始查找 AsParallel().ToList().ForEach(ac => { //抓取圖片,因為有空的,所以拿變量存起來 HtmlNode node = ac.SelectSingleNode(".//p[@class='post_item_summary']/a/img"); list.Add(new Result { url = ac.SelectSingleNode(".//a[@class='titlelnk']").Attributes["href"].Value, title = ac.SelectSingleNode(".//a[@class='titlelnk']").InnerText, //圖片如果為空,顯示默認圖片 img = node == null ? "http ://www.cnblogs.com//Content/img/avatar.png" : node.Attributes["src"].Value, content = ac.SelectSingleNode(".//p[@class='post_item_summary']").InnerText }); }); foreach (Result item in list) { this.listBox1.Items.Add(item.title); } } /// <summary> /// 頁面抓取結果 /// </summary> public class Result { /// <summary> /// 鏈接 /// </summary> public string url { get; set; } /// <summary> /// 標題 /// </summary> public string title { get; set; } /// <summary> /// 頭像地址 /// </summary> public string img { get; set; } /// <summary> /// 正文內容 /// </summary> public string content { get; set; } }
示例2:下載微軟文檔
using HtmlAgilityPack; using System; using System.Collections.Generic; using System.IO; using System.Text; namespace ConsoleApp4 { internal class Program { private static void Main(string[] args) { //網頁地址: string Url = "https://docs.microsoft.com/zh-cn/aspnet/mvc/overview/getting-started/getting-started-with-ef-using-mvc/implementing-inheritance-with-the-entity-framework-in-an-asp-net-mvc-application"; List<string> list = new List<string>(); ; HtmlWeb htmlWeb = new HtmlWeb(); htmlWeb.OverrideEncoding = Encoding.UTF8; HtmlDocument htmlDoc = htmlWeb.Load(Url); HtmlNode node = htmlDoc.DocumentNode.SelectSingleNode("//main[@id='main']"); //去掉英文翻譯 var a = node.SelectNodes("//span[@class='sxs-lookup']"); foreach (HtmlNode b in a) { b.Remove(); } string src = ""; //圖片相對路徑改成絕對路徑 var imgNode = node.SelectNodes("//img[@data-linktype='relative-path']"); foreach (HtmlNode node1 in imgNode) { src = node1.GetAttributeValue("src", ""); var url = new Uri(htmlWeb.ResponseUri, src); node1.SetAttributeValue("src", url.AbsoluteUri); } //鏈接路徑轉換 var hrefNode = node.SelectNodes("//a[@data-linktype='relative-path']|//a[@data-linktype='absolute-path']"); foreach (HtmlNode node1 in hrefNode) { src = node1.GetAttributeValue("href", ""); var url = new Uri(htmlWeb.ResponseUri, src); node1.SetAttributeValue("href", url.AbsoluteUri); } //找到所有的H2標簽,然後加上順序。 var h2Node = node.SelectNodes("//h2"); var arr = new string[] { "一", "二", "三", "四", "五", "六", "七", "八", "九", "十", "十一", "十二", "十三", "十四", "十五", "十六", "十七", "十八", "十九", "二十" }; if (h2Node != null) { for (int i = 0; i < h2Node.Count; i++) { h2Node[i].InnerHtml = arr[i] + "、" + h2Node[i].InnerHtml; //找到所有的H3標簽,然後加上順序。 var h3Node = h2Node[i].SelectNodes("following-sibling::h2|following-sibling::h3"); if (h3Node is null) break; for (int j = 0; j < h3Node.Count; j++) { if (h3Node[j].Name == "h2") break; else h3Node[j].InnerHtml = (j + 1) + "、" + h3Node[j].InnerHtml; } } } HtmlNode myNOde = htmlDoc.CreateElement("div"); //去掉前面無用的部分 var OK = node.SelectNodes("nav[1]/following-sibling::*"); myNOde.AppendChildren(OK); //添加原文連接: HtmlNode nodeOriUrl = htmlDoc.CreateElement("p"); nodeOriUrl.InnerHtml = "原文:<a href='" + htmlWeb.ResponseUri + "'>" + htmlWeb.ResponseUri + "</a>"; myNOde.PrependChild(nodeOriUrl); //寫入到本地文件 TextWriter wr = new StreamWriter(@"aa.html"); myNOde.WriteTo(wr); wr.Close(); } } }
四、Fizzler.Systems.HtmlAgilityPack:
Hazz為HTMLAgilityPack實現CSS選擇器。它基於Fizzler,一個通用的CSS選擇器解析器和生成器庫。
Hazz以前稱為Fizzler.Systems.HtmlAgilityPack。
// Load the document using HTMLAgilityPack as normal var html = new HtmlDocument(); html.LoadHtml(@" <html> <head></head> <body> <div> <p class='content'>Fizzler</p> <p>CSS Selector Engine</p></div> </body> </html>"); // Fizzler for HtmlAgilityPack is implemented as the // QuerySelectorAll extension method on HtmlNode var document = html.DocumentNode; // yields: [<p class="content">Fizzler</p>] document.QuerySelectorAll(".content"); // yields: [<p class="content">Fizzler</p>,<p>CSS Selector Engine</p>] document.QuerySelectorAll("p"); // yields empty sequence document.QuerySelectorAll("body>p"); // yields [<p class="content">Fizzler</p>,<p>CSS Selector Engine</p>] document.QuerySelectorAll("body p"); // yields [<p class="content">Fizzler</p>] document.QuerySelectorAll("p:first-child");
到此這篇關於C#使用HtmlAgilityPack組件解析html文檔的文章就介紹到這瞭。希望對大傢的學習有所幫助,也希望大傢多多支持WalkonNet。
推薦閱讀:
- c# 爬取優酷電影信息(2)
- JavaScript處理XML DOM、XPath和XSLT方法詳解
- JavaScript深入介紹WebAPI的用法
- Manipulation-TypeScript DOM操作示例解析
- JavaScript仿京東實現秒殺倒計時案例詳解