C# 通过Html Agility Pack实现快速解析Html

简介

  现在越来越多的场景需要我们使用网络爬虫,抓取相关数据便于我们使用,今天我主要总结一下HAP(Html Agility Pack)如何高效、快速、准确的解析我们抓取到的html中各元素节点及数据。

优势

  在.NET技术下,解析html工具也很多,比如很多人可能会使用htmlparser,或者微软的MSHTML,htmlparser虽然比较易上手,但是相对应的解析速度较慢,而Html Agility Pack解析速度相当快,并且开源,易用,它可以帮助我们解析html文档就像用XmlDocument类来解析xml一样轻松、方便。

  传送门:官网地址Github开源代码地址

方法介绍

  其实Html Agility Pack的类不是很多,我们解析Html的时候,用到的也就HtmlDocument和HtmlNode(还有HtmlNodeCollection集合类)这几个类。官网也有相对应的API文档说明,其实真的是简单易懂,传送门:API文档

一、如何加载Html?

HtmlDocument类定义; 多个重载Load方法来实现不同方式的Html加载,主要常见的有三种方式;从文件加载、从字符串加载、从网页链接加载。

//1.从物理路径的文件加载
var doc = new HtmlDocument();
doc.Load(filePath);//文件路径

//2.从字符串当中加载
var doc = new HtmlDocument();
doc.LoadHtml(html);

//3.从网页的Url链接加载
var url = "https://blog.csdn.net/yanghaolong";
var web = new HtmlWeb();
var doc = web.Load(url);

 二、如何解析Dom元素获取到相关元素下的数据

这个时候我们需要用到HtmlNodeCollection和HtmlNode这两个类,我们把Html每个标签看作一个Node,所有我们想到定位到某个标签的内容,就需要知道这个标签的相关属性。顺便说一下,HtmlNode类实现了IXPathNavigable接口,这说明了它可以通过xpath来定位数据了,如果你对解析XML格式数据的XmlDocument类了解的话,特别是使用过了SelectNodes()和SelectSingleNode()方法的人来说,对使用HtmlNode类将会很熟悉。其实Html Agility Pack内部是把html解析成xml文档格式了的,所以支持xml中的一些常用查询方式。下面通过简单示例对HtmlNode的一些主要的常用成员作简要的说明。

示例:

<!DOCTYPE html>
<html lang="zh-cn">
<head>
<meta charset="utf-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>HAP示列</title>
</head>
<body>
<div id="home">
<div id="header">
    <div id="vTitle">         
    <h1><a id="Header1_HeaderTitle" class="headermaintitle" href="https://blog.csdn.net/yanghaolong">Harlan的专栏</a></h1>
    <h2>智慧生活源于每一个技术奉献人</h2>
    </div>   <!--end: blogTitle 博客的标题和副标题 -->
    <div id="navigator">
<ul id="navList">
    <li><a id="blog_nav_sitehome" class="menu" href="http://xxx/">测试1</a></li>
    <li><a id="blog_nav_myhome" class="menu" href="http://xxx/">测试2</a></li>
</ul>
</div><!--end: header 头部 -->
<div id="main"></div><!--end: 正文 -->
<div id="footer"></div><!--end: 底部 -->
</div>
</body>
</html>

一般Html最常见的是div标签元素,它可能会定义一些属性,比例本文当中的<div id="vTitle">,有些不是id属性,是class属性,这个根据实际情况而定,要灵活变通.根据实际情况而定.

(1)通过ID属性(或者其他属性)来选择对应的节点

  通用格式:@id=‘xxxx’(id可以是其他属性等等),比如我们要定位示列代码中标题。其中通过XPath在HTML中解析查找各元素内容

HtmlAgilityPack.HtmlDocument doc = new HtmlAgilityPack.HtmlDocument();
doc.LoadHtml(url)//html URL
//下面的意思是:通过属性id的值,来定位header下的vTitle节点信息
 HtmlNode titleNode = doc.DocumentNode.SelectSingleNode("//div[@id='header']/div[@id='vTitle']");

我们还可以不通过属性id去定位,还有通过索引去定位,如下所示,这个效果和上面是等同的:

 //下面的意思是:通过索引定位,div[2]是表示根节点的第二个
HtmlNode titleNode = doc.DocumentNode.SelectSingleNode("//div[2]/div[1]");

备注:注意路径里"//"表示从根节点开始查找,两个斜杠‘//’表示查找所有childnodes;一个斜杠'/'表示只查找第一层的childnodes(即不查找grandchild);点斜杠"./"表示从当前结点而不是根结点开始查找。我们接着上面titleNode节点。

//下面的意思是:通过当前titleNode节点,获取便签h1的节点
 HtmlNode IDNode = titleNode.SelectSingleNode("./h1");

(2)如何获取节点文本内容

  接着上面(1)所说的,通过代码“HtmlNode IDNode = doc.DocumentNode.SelectSingleNode("//div[@id='header']/div[@id='vTitle']/h1") ”获取到了IDNode的节点,那么接下来,我们需要这么获取具体的文本值呢?有三种方式获取OuterHtml,InnerHtml和InnerText。

  HtmlNode类设计了OuterHtml属性和InnerHtml属性用于获取当前节点的Html源码。两者不同之处是,OuterHtml属性返回的是包含当前节点的Html代码在内的所有Html代码,而InnerHtml属性返回的是当前节点里面子节点的所有Html代码,InnerText属性过滤掉了所有的Html标记代码,只返回文本值。具体用哪种方式,要根据我们实际情况而定,一般InnerHtml和InnerText使用的频率比较多。如下所示:

//我们获取内容
IDNode.OuterHtml ///返回结果是:<h1><a id="Header1_HeaderTitle" class="headermaintitle" href="https://blog.csdn.net/yanghaolong">Harlan的专栏</a></h1>
IDNode.InnerHtml ///返回结果是:<a id="Header1_HeaderTitle" class="headermaintitle" href="https://blog.csdn.net/yanghaolong/">Harlan的专栏</a>
IDNode.InnerText ///返回结果是:Harlan的专栏

(3)如何获取节点属性值

  假如我们上面Html数据当中,博主博客地址,在标签<div id="header">里的<a>标签里,这个时候就需要使用HtmlNode下的Attribute属性了。

string value = doc.DocumentNode.SelectSingleNode("//div[@id='header']/div[@id='vTitle']/a").Attributes["href"].Value;

 (4)如何获取某个标签的所有节点

   我们如果获取前面Html数据的li所有分类,这个时候需要使用方法SelectNodes了

HtmlNodeCollection uiListNodes = doc.DocumentNode.SelectNodes("//ui[@id='navList']/li");

 更多的方法大家可以到官网的API文档进行了解,这里就不做更多的说明。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值