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屬性
  • NameHtml元素名
  • 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。

推薦閱讀: