一、概述

HtmlAgilityPack(以下简称HAP)是一个基于.Net的、第三方免费开源的微型类库,主要用于在服务器端解析html文档。

HtmlAgilityPack为网页提供了标准的DOM API和XPath导航。使用WebBrowser和HttpWebRequest下载的网页可以用Html Agility Pack来解析。

Xpath表达式的参考文档可见:http://www.w3school.com.cn/xpath/xpath_syntax.asp

参考:

GitHub:https://github.com/zzzprojects/html-agility-pack/releases

官网:https://html-agility-pack.net/

https://www.nuget.org/packages/HtmlAgilityPack/

二、属性和方法

HtmlAgilityPack中的HtmlNode类与XmlNode类差不多,HtmlDocument类与XmlDocument类差不多。下面来看看该类提供功能。

属性

  • Attributes 获取节点的属性集合
  • ChildNodes获取子节点集合(包括文本节点)
  • Closed该节点是否已关闭(</xxx>)
  • ClosingAttributes在关闭标签的属性集合
  • FirstChild 获取第一个子节点
  • HasAttributes 判断该节点是否含有属性
  • HasChildNodes 判断该节点是否含有子节点
  • HasClosingAttributes  判断该节点的关闭标签是否含有属性(</xxx class="xxx">)
  • Id 获取该节点的Id属性
  • InnerHtml 获取该节点的Html代码
  • InnerText  获取该节点的内容,与InnerHtml不同的地方在于它会过滤掉Html代码,而InnerHtml是连Html代码一起输出
  • LastChild  获取最后一个子节点
  • Line  获取该节点的开始标签或开始代码位于整个HTML源代码的第几行(行号)
  • NameHtml元素名
  • NextSibling 获取下一个兄弟节点
  • NodeType    获取该节点的节点类型
  • OuterHtml 整个节点的代码
  • OwnerDocument节点所在的HtmlDocument文档
  • ParentNode:获取该节点的父节点
  • PreviousSibling: 获取前一个兄弟节点
  • StreamPosition: 该节点位于整个Html文档的字符位置
  • XPath:  根据节点返回该节点的XPath

方法:

  • void Load(string path);      从路径中加载一个文档
  • IEnumerable<HtmlNode> Ancestors();               返回此元素的所有上级节点的集合。
  • HtmlNode AppendChild(HtmlNode newChild);   将参数元素追加到为调用元素的子元素(追加在最后)
  • HtmlNode PrependChild(HtmlNode newChild);    将参数中的元素作为子元素,放在调用元素的最前面
  • IEnumerable<HtmlAttribute> ChildAttributes(string name);     获取所有子元素的属性(参数名要与元素名匹配)
  • HtmlNode Clone();                          本节点克隆到一个新的节点
  • void CopyFrom(HtmlNode node);  创建重复的节点和其下的子树。
  • XPathNavigator CreateNavigator();                  返回的一个对于此文档的XPathNavigator
  • static HtmlNode CreateNode(string html);   静态方法,允许用字符串创建一个新节点
  • XPathNavigator CreateRootNavigator();               创建一个根路径的XPathNavigator
  • IEnumerable<HtmlNode> DescendantNodes();            获取所有子代节点
  • HtmlNode Element(string name);  根据参数名获取一个元素
  • IEnumerable<HtmlNode> Elements(string name);          根据参数名获取匹配的元素集合
  • bool GetAttributeValue(string name, bool def);  帮助方法,用来获取此节点的属性的值(布尔类型)。如果未找到该属性,则将返回默认值。
  • HtmlNode InsertAfter(HtmlNode newChild, HtmlNode refChild);  将一个节点插入到第二个参数节点的后面,与第二个参数是兄弟关系
  • HtmlNode InsertBefore(HtmlNode newChild, HtmlNode refChild);   讲一个节点插入到第二个参数节点的后面,与第二个参数是兄弟关系
  • static bool IsEmptyElement(string name);    确定是否一个空的元素节点。
  • static bool IsOverlappedClosingElement(string text);  确定是否文本对应于一个节点可以保留重叠的结束标记。
  • void Remove();  从父集合中移除调用节点
  • HtmlNodeCollection SelectNodes(string xpath);           根据XPath获取一个节点集合
  • HtmlNode SelectSingleNode(string xpath);              根据XPath获取唯一的一个节点
  • HtmlAttribute SetAttributeValue(string name, string value);  设置调用节点的属性
  • string WriteContentTo();  将该节点的所有子级都保存到一个字符串中。
  • string WriteTo();                           将当前节点保存到一个字符串中。
  • void 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; }
}

HtmlAgilityPack解析html文档的更多相关文章

  1. C#爬虫(04):HtmlAgilityPack解析html文档

    原文链接 https://www.cnblogs.com/springsnow/p/13278283.html 目录 一.爬虫概述 1.使用浏览器获取页面源码 2.HTML解析组件 二.HtmlAgi ...

  2. .Net解析html文档类库HtmlAgilityPack完整使用说明

    在前几篇文章中([搜房网房产数据采集程序demo--GeckoWebBrowser实例] )都有提到一个解析html的C#类库HtmlAgilityPack, 今天终于有时间整理一下,并把Demo分享 ...

  3. 网络电视精灵~分析~~~~~~简单工厂模式,继承和多态,解析XML文档,视频项目

    小总结: 所用技术: 01.C/S架构,数据存储在XML文件中 02.简单工厂模式 03.继承和多态 04.解析XML文档技术 05.深入剖析内存中数据的走向 06.TreeView控件的使用 核心: ...

  4. 使用dom4j解析XML文档

    dom4j的包开源包,不属于JDK里面,在myeclipse中要单独导入在项目中,这里不累赘了 做这个过程,很慢,因为很多方法没用过不熟悉,自己得去查帮助文档,而且还得去试,因为没有中文版,英文翻译不 ...

  5. 四种生成和解析XML文档的方法详解(介绍+优缺点比较+示例)

    众所周知,现在解析XML的方法越来越多,但主流的方法也就四种,即:DOM.SAX.JDOM和DOM4J 下面首先给出这四种方法的jar包下载地址 DOM:在现在的Java JDK里都自带了,在xml- ...

  6. java解析xml文档(dom)

    DOM解析XML文档 读取本地的xml文件,通过DOM进行解析,DOM解析的特点就是把整个xml文件装载入内存中,形成一颗DOM树形结构,树结构是方便遍历和和操纵. DOM解析的特性就是读取xml文件 ...

  7. java 解析XML文档

    Java 解析XML文档 一.解析XML文档方式: 1.DOM方式:将整个XML文档读取到内存中,按照XML文件的树状结构图进行解析. 2.SAX方式:基于事件的解析,只需要加载XML中的部分数据,优 ...

  8. DOM生成XML文档与解析XML文档(JUNIT测试)

    package cn.liuning.test; import java.io.File; import java.io.IOException; import javax.xml.parsers.D ...

  9. [置顶] stax解析xml文档的6种方式

    原文链接:http://blog.csdn.net/u011593278/article/details/9745271 stax解析xml文档的方式: 基于光标的查询: 基于迭代模型的查找: 基于过 ...

随机推荐

  1. linux awk的用法

    linux awk的用法 <pre>[root@iZ23uewresmZ ~]# cat /home/ceshis.txtb 12 42 30 b 03 43 25 a 08 10 16 ...

  2. 学习数据结构Day4

    链表 之前看过了动态数组,栈和队列,虽然我们把第一个叫做动态数组,但是,他们的底层实质上还是静态数组.靠 resize来实现动态数组.而链表是真正的数据结构 链表需要一个节点. 数据存储在链表中 相当 ...

  3. STL源码剖析——序列式容器#2 List

    list就是链表的实现,链表是什么,我就不再解释了.list的好处就是每次插入或删除一个元素,都是常数的时空复杂度.但遍历或访问就需要O(n)的时间. List本身其实不难理解,难点在于某些功能函数的 ...

  4. Python基础 — eval 函数的作用

    eval函数就是实现list.dict.tuple与str之间的相互转化str函数把list,dict,tuple转为为字符串 # 字符串转换成列表a = "[[1,2], [3,4], [ ...

  5. 微信H5页面前端开发,大多数人都会遇到的几个兼容性坑

    最近给公司微信公众号,写了微信h5业务页面,总结分享一下前端开发过程中的几个兼容性坑,项目直接拿的公司页面,所以下文涉及图片都模糊处理了. 1.ios端兼容input光标高度 问题详情描述:input ...

  6. Appium_Page object设计模式

    Page object设计模式思维,把app按页面去划分,一个页面就是一个page对象 每个页面的元素集中管理.页面上按钮操作方法单独封装 # __author__ = " Caric Le ...

  7. ssh密码正确无法连接

    新建了一个虚拟机,准备用ssh 连接管理,提示权限不足, 账号密码没问题,防火墙没有开 打开ssh服务的配置文件,默认在  /etc/ssh/sshd_config (不是 ssh_config) 检 ...

  8. 结合consul raft库理解raft

    一 入口 github.com/hashicorp/consul/agent/consul/server.go func (s *Server) setupRaft() error { 状态机,用于c ...

  9. 不是所有OutOfMemoryError异常都跟内存有关

    一个老鸟遇到一个稀奇的问题后,如果只是想想,那么可能会失去一次丰富自己的机会. 如果从开始养成一个习惯,把所有难解决的问题都记录下来,面试的时候,也可能是给自己一次机会 *************** ...

  10. JDK提供的原子类和AbstractQueuedSynchronizer(AQS)

    大致分成: 1.原子更新基本类型 2.原子更新数组 3.原子更新抽象类型 4.原子更新字段 import java.util.concurrent.atomic.AtomicInteger; impo ...