简介

  现在越来越多的场景需要我们使用网络爬虫,抓取相关数据便于我们使用,今天我们要讲的主角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文档

Question 1、如何加载Html?

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

  示例:

 // 从物理路径的文件加载
var doc = new HtmlDocument();
doc.Load(filePath);//文件路径 // 从Stream当中加载
var doc = new HtmlDocument();
doc.LoadHtml(html); // 从网页的Url链接加载
var url = "http://www.cnblogs.com/xuliangxing/";
var web = new HtmlWeb();
var doc = web.Load(url);

  以Stream对象为主的重载方法:

()public void Load(Stream stream)    ///从指定的Stream对象中加载html;
()public void Load(Stream stream, bool detectEncodingFromByteOrderMarks) ///指定是否从顺序字节流中解析编码格式
()public void Load(Stream stream, Encoding encoding) ///指定编码格式
()public void Load(Stream stream, Encoding encoding, bool detectEncodingFromByteOrderMarks)
()public void Load(Stream stream, Encoding encoding, bool detectEncodingFromByteOrderMarks, int buffersize) ///缓冲区大小

  以指定的物理路径为主的重载方法:

()public void Load(string path)
()public void Load(string path, bool detectEncodingFromByteOrderMarks) ///指定是否从顺序字节流中解析编码格式
()public void Load(string path, Encoding encoding) ///指定编码格式
()public void Load(string path, Encoding encoding, bool detectEncodingFromByteOrderMarks)
()public void Load(string path, Encoding encoding, bool detectEncodingFromByteOrderMarks, int buffersize)

 Question 2、如何精准定位到我们需要的数据

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

  就以我博客园主页为例,希望大家在此基础上能够举一反三,这里只做抛砖引玉,界面图如下:

  后台Html代码,我抓取了部分代码拿来做示例

 <!DOCTYPE html>
<html lang="zh-cn">
<head>
<meta charset="utf-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>法号阿兴 - 博客园</title>
</head>
<body>
<div id="home">
<div id="header">
<div id="blogTitle">
<a id="lnkBlogLogo" href="http://www.cnblogs.com/xuliangxing/"><img id="blogLogo" src="/Skins/custom/images/logo.gif" alt="返回主页" /></a>
<h1><a id="Header1_HeaderTitle" class="headermaintitle" href="http://www.cnblogs.com/xuliangxing/">法号阿兴</a></h1>
<h2>你的能力还驾驭不了你的目标时,就应该沉下心来历练</h2>
</div> <!--end: blogTitle 博客的标题和副标题 -->
<div id="navigator">
<ul id="navList">
<li><a id="blog_nav_sitehome" class="menu" href="http://www.cnblogs.com/">博客园</a></li>
<li><a id="blog_nav_myhome" class="menu" href="http://www.cnblogs.com/xuliangxing/">首页</a></li>
<li><a href="http://news.cnblogs.com/">新闻</a></li>
<li><a id="blog_nav_newpost" class="menu" rel="nofollow" href="https://i.cnblogs.com/EditPosts.aspx?opt=1">新随笔</a></li>
<li><a id="blog_nav_contact" accesskey="9" class="menu" rel="nofollow" href="https://msg.cnblogs.com/send/%E6%B3%95%E5%8F%B7%E9%98%BF%E5%85%B4">联系</a></li>
<li><a id="blog_nav_admin" class="menu" rel="nofollow" href="https://i.cnblogs.com/">管理</a></li>
<li><a id="blog_nav_rss" class="menu" href="http://www.cnblogs.com/xuliangxing/rss">订阅</a>
<a id="blog_nav_rss_image" class="aHeaderXML" href="http://www.cnblogs.com/xuliangxing/rss"><img src="//www.cnblogs.com/images/xml.gif" alt="订阅" /></a></li>
</ul>
</div><!--end: header 头部 -->
<div id="main"></div><!--end: 正文 -->
<div id="footer"></div><!--end: 底部 -->
</div>
</body>
</html>

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

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

  通用格式:@id=‘xxxx’(id可以是其他属性等等),比如我们要定位到本文博客主页的标题和副标题内容。

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

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

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

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

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

  讲解了上面这些,大家应该已经能够明白了Html Agility Pack的基本使用方法,那么如何一次性获取博主的ID呢?

 HtmlNode IDNode = doc.DocumentNode.SelectSingleNode("//div[@id='header']/div[@id='blogTitle']/h1");

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

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

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

 //我们获取博客ID
IDNode.OuterHtml ///返回结果是:<h1><a id="Header1_HeaderTitle" class="headermaintitle" href="http://www.cnblogs.com/xuliangxing/">法号阿兴</a></h1>
IDNode.InnerHtml ///返回结果是:<a id="Header1_HeaderTitle" class="headermaintitle" href="http://www.cnblogs.com/xuliangxing/">法号阿兴</a>
IDNode.InnerText ///返回结果是:法号阿兴

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

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

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

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

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

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

 Question 3、Html Agility Pack进行删除操作

  Html Agility Pack是可以对Html做删除操作的,具体的可以参考官网的API,这里我们讲下最常见

(1)如何去掉外层的html tag只留下文本内容

  回到我们刚刚上面讲到的地方,用remove方法。假设要删除上文结点<a id="Header1_HeaderTitle" class="headermaintitle" href="http://www.cnblogs.com/xuliangxing/">法号阿兴</a>,你想留下博客名称而不要<a></a>的话,那你需要先得到这个Html结点,通过remove方法删除掉多余的HTML Tag假设该节点叫Node:

Node.ParentNode.RemoveChild(Node,true); 

  参数true表示留下grandchild,在这里即博主博客ID内容; false表示将此结点连同其grandchilds一起删除。

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

 PS:如有疑问,请留言,未经允许,不得私自转载,转载请注明出处:http://www.cnblogs.com/xuliangxing/p/8004403.html

C# 网络爬虫利器之Html Agility Pack如何快速实现解析Html的更多相关文章

  1. 开源项目Html Agility Pack实现快速解析Html

    这是个很好的的东西,以前做Html解析都是在用htmlparser,用的虽然顺手,但解析速度较慢,碰巧今天找到了这个,就拿过来试,一切出乎意料,非常爽,推荐给各位使用. 下面是一些简单的使用技巧,希望 ...

  2. 芝麻HTTP: Python爬虫利器之Requests库的用法

    前言 之前我们用了 urllib 库,这个作为入门的工具还是不错的,对了解一些爬虫的基本理念,掌握爬虫爬取的流程有所帮助.入门之后,我们就需要学习一些更加高级的内容和工具来方便我们的爬取.那么这一节来 ...

  3. Python的爬虫利器之urllib

    urllib包 urllib是一个包含几个模块来处理请求的库:  - urllib.request发送http请求  - urllib.error处理请求过程中出现的异常  - urllib.pars ...

  4. 芝麻HTTP: Python爬虫利器之PyQuery的用法

    前言 你是否觉得 XPath 的用法多少有点晦涩难记呢? 你是否觉得 BeautifulSoup 的语法多少有些悭吝难懂呢? 你是否甚至还在苦苦研究正则表达式却因为少些了一个点而抓狂呢? 你是否已经有 ...

  5. 芝麻HTTP:Python爬虫利器之Xpath语法与lxml库的用法

    安装 ​pip install lxml 利用 pip 安装即可 XPath语法 XPath 是一门在 XML 文档中查找信息的语言.XPath 可用来在 XML 文档中对元素和属性进行遍历.XPat ...

  6. Python爬虫利器之Beautiful Soup,Requests,正则的用法(转)

    https://cuiqingcai.com/1319.html https://cuiqingcai.com/2556.html https://cuiqingcai.com/977.html

  7. 一只简单的网络爬虫(基于linux C/C++)————利用正则表达式解析页面

    我们向一个HTTP的服务器发送HTTP的请求后,服务器会返回可能一个HTML页面(当然也可以是其他的资源),我们可以利用返回的HTML页面,在其中寻找其他的Url,例如我们可以这样在浏览器上查看一下H ...

  8. Day01_WebCrawler(网络爬虫)

    学于黑马和传智播客联合做的教学项目 感谢 黑马官网 传智播客官网 微信搜索"艺术行者",关注并回复关键词"webcrawler"获取视频和教程资料! b站在线视 ...

  9. Html Agility Pack解析Html(C#爬虫利器)

    有个需求要写网络爬虫,以前接触过一个叫Html Agility Pack这个解析html的库,这次又要用到,然而发现以前咋用的已经不记得了,现在从头开始记录一下使用过程. Html Agility P ...

随机推荐

  1. [原创]AndroBugs_Framework Android漏洞扫描器介绍

    [原创]AndroBugs_Framework Android漏洞扫描器介绍 1 AndroBugs_Framework Android 漏洞扫描器简介 一款高效的Android漏洞扫描器,可以帮助开 ...

  2. Oracle优化网上常见的5个错误观点

    最近系统的研究了一下ORACLE SQL语句性能调优,在此大言不惭的得出一个观点——网上很多性能调优的结论都是错误的或者不周全的.现在的DBA大牛些都太低调了,不出来斧正一下,小弟来借这个机会吐槽一下 ...

  3. Quartz Cron表达式 每周、每月执行一次

    原文:https://blog.csdn.net/qq_33432559/article/details/75633767 系统中通常有些需要自动执行的任务,这些任务可能每隔一段时间就要执行一次,也可 ...

  4. bootstrap-table方法之:合并单元格

    方法一 通过mergeCells方法 演示地址:http://issues.wenzhixin.net.cn/bootstrap-table/methods/mergeCells.html Merge ...

  5. 访问天地图WMTS服务的正确姿势

    天地图2018版对天地图应用开发流程进行了升级改造,主要有两点变化: (1)接口升级为tianditu.gov.cn政府域名,支持HTTP/HTTPS协议,原有服务域名tianditu.com继续保留 ...

  6. 转发:entos7修改文件夹权限和用户名用户组

    Linux系统下经常遇到文件或者文件夹的权限问题,或者是因为文件夹所属的用户问题而没有访问的权限.根据我自己遇到的情况,对这类问题做一个小结.在命令行使用命令“ll”或者“ls -a”,可以查看文件或 ...

  7. [C#] 将NLog输出到RichTextBox,并在运行时动态修改日志级别过滤

    作者: zyl910 一.缘由 NLog是一个很好用的日志类库.利用它,可以很方便的将日志输出到 调试器.文件 等目标,还支持输出到窗体界面中的RichTextBox等目标. 而且它还支持在运行时修改 ...

  8. python两个 list 获取交集,并集,差集的方法

    1. 获取两个list 的交集 #方法一: a=[2,3,4,5] b=[2,5,8] tmp = [val for val in a if val in b] print tmp #[2, 5] # ...

  9. OpenLayers Node环境安装运行构建-支持Vue集成OpenLayers

    NodeJS 环境安装包下载:https://nodejs.org/zh-cn/download/ 安装vue-cli3.0.1: https://cli.vuejs.org/guide/instal ...

  10. CDC在sql server 2017中无法使用的问题

    Symptom === sp_MScdc_capture_job in the CDC job raised error message Msg 217, Level 16, State 1, Pro ...