C#使用HtmlAgilityPack组件解析html文档

2022-06-14 11:47:25

一、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>

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>Closed:该节点是否已关闭(</xxx>)ClosingAttributes在关闭标签的属性集合StreamPosition: 该节点位于整个Html文档的字符位置XPath: 根据节点返回该节点的XPath

    2、方法:

      Load (string>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(): 返回的一个对于此文档的XPathNavigatorCreateNode(string html): 静态方法,允许用字符串创建一个新节点CreateRootNavigator(): 创建一个根路径的XPathNavigatorInsertAfter(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文档的文章就介绍到这了。希望对大家的学习有所帮助,也希望大家多多支持易采站长站。