强大而灵活的的Html解析器——Html Agility Pack
一、概述
Html Agility Pack 简称HAP,是一个强大而灵活的解析Html DOM的.Net类库。
二、官方链接
官网:http://html-agility-pack.net/
NuGet: https://www.nuget.org/packages/HtmlAgilityPack/
Github:https://github.com/zzzprojects/html-agility-pack
三、用法及示例
1、解析前需要加载资源,有四种方式载入:
(1) File
var path = @"D:\test.html"; var doc = new HtmlDocument();
doc.Load(path);
以上的path是自己的文件路径,这样html被加载到了Doc之后就可以解析了。
(2) String
var html = @"<!DOCTYPE html>
<html>
<body>
<h1>This is <b>bold</b> heading</h1>
<p>This is <u>underlined</u> paragraph</p>
<h2>This is <i>italic</i> heading</h2>
</body>
</html> "; var htmlDoc = new HtmlDocument();
htmlDoc.LoadHtml(html); var htmlBody = htmlDoc.DocumentNode.SelectSingleNode("//body");
以上的html是一个html格式的字符串。通过LoadHtml加载到了htmlDoc。在爬虫过程中通过url获取的html内容字符串后,就可以通过这种方式加载。
(3) Web
var html = @"http://html-agility-pack.net/"; HtmlWeb web = new HtmlWeb(); var htmlDoc = web.Load(html);
这个方法则是直接通过url加载。如果是只有url,则较之前一种方法更为简单,不需要再另写通过url获取html内容字符串的方法。
(4) Browser
string url = "http://html-agility-pack/from-browser"; var web1 = new HtmlWeb();
var doc1 = web1.LoadFromBrowser(url, o =>
{
var webBrowser = (WebBrowser) o; // WAIT until the dynamic text is set
return !string.IsNullOrEmpty(webBrowser.Document.GetElementById("uiDynamicText").InnerText);
});
var t1 = doc1.DocumentNode.SelectSingleNode("//div[@id='uiDynamicText']").InnerText; var web2 = new HtmlWeb();
var doc2 = web2.LoadFromBrowser(url, html =>
{
// WAIT until the dynamic text is set
return !html.Contains("<div id=\"uiDynamicText\"></div>");
});
var t2 = doc2.DocumentNode.SelectSingleNode("//div[@id='uiDynamicText']").InnerText; Console.WriteLine("Text 1: " + t1);
Console.WriteLine("Text 2: " + t2);
此方法需要在WinForm中使用。通过LoadFromBrowser方法来加载.
2、选择器
(1) SelectNodes(),选择与xPath表达式匹配的节点,如果不存在匹配的节点,则返回null.
示例1:返回匹配表达式“/td/input”的节点集合
var htmlDoc = new HtmlDocument();
htmlDoc.LoadHtml(html);
string name = htmlDoc.DocumentNode
.SelectNodes("//td/input");
当需要只返回匹配的第一个节点时,用.first。
string name = htmlDoc.DocumentNode
.SelectNodes("//td/input")
.First()
用first的前提是这种节点要存在。否则返回的是null时不能再用first。因此可以先获取匹配的节点集合,判断不为空的情况下,再用first:
var inputNodes = htmlDoc.DocumentNode.SelectNodes("//td/input");
if (inputNodes!=null)
{
string name = inputNodes.First();
}
示例2:通过class或者id等返回匹配节点,以下是为了获取class='news-item'的所有div节点。
var mainNode = htmlDoc.DocumentNode.SelectNodes(@"//div[@class='news-item']");
当然,div可以根据需要换成span、h1、img等节点。class也可以根据需要换成id或其他。
(2) SelectSingleNode 。获取第一个匹配Xpath表达式的节点。节点不存在则返回null。
示例1:
var htmlDoc = new HtmlDocument();
htmlDoc.LoadHtml(html); string name = htmlDoc.DocumentNode
.SelectSingleNode("//td/input");
示例2:
var firstNode = htmlDoc.DocumentNode.SelectSingleNode(@"//div[@class='viewport']");
(3)结合linq的使用更强大: 通过where方法或者firstordefault方法,以及节点的特性或者节点的内容等获取节点。
示例:
HtmlWeb web = new HtmlWeb();
var doc = web.Load(model.Url);
var textNode = doc.DocumentNode.Descendants("div").FirstOrDefault(m => m.GetAttributeValue("class", "") == "text" && m.GetAttributeValue("dir", "") == "ltr"); var tdNode = htmlDoc.DocumentNode.SelectNodes(@"//td[@colspan='3']").Where(n => n.InnerHtml.Contains("<a href=") && n.InnerHtml.Contains("<p align=")).FirstOrDefault();
3、通过以上方式获取节点后,就可以对节点进行操作了。
InnerHtml:获取或设置节点内的html。
var htmlDoc = new HtmlDocument();
htmlDoc.LoadHtml(html); var htmlNodes = htmlDoc.DocumentNode.SelectNodes("//body/h1"); foreach (var node in htmlNodes)
{
Console.WriteLine(node.InnerHtml);
}
InnerText:获取或设置节点内的text。
var htmlDoc = new HtmlDocument();
htmlDoc.LoadHtml(html); var htmlNodes = htmlDoc.DocumentNode.SelectNodes("//body/h1"); foreach (var node in htmlNodes)
{
Console.WriteLine(node.InnerText);
}
AppendChild:向指定节点的末尾增加子节点:
var htmlDoc = new HtmlDocument();
htmlDoc.LoadHtml(html); var htmlBody = htmlDoc.DocumentNode.SelectSingleNode("//body"); HtmlNode h2Node = HtmlNode.CreateNode("<h2> This is h2 heading</h2>"); htmlBody.AppendChild(h2Node);
Remove:移除节点
var htmlDoc = new HtmlDocument();
htmlDoc.LoadHtml(html);
var htmlBody = htmlDoc.DocumentNode.SelectSingleNode("//body");
HtmlNode node = htmlBody.ChildNodes[];
node.Remove();
遍历
ChildNodes:获取所有子节点:
var htmlDoc = new HtmlDocument();
htmlDoc.LoadHtml(html); var htmlBody = htmlDoc.DocumentNode.SelectSingleNode("//body"); HtmlNodeCollection childNodes = htmlBody.ChildNodes; foreach (var node in childNodes)
{
if (node.NodeType == HtmlNodeType.Element)
{
Console.WriteLine(node.OuterHtml);
}
}
FirstChild:获取第一个子节点:
var htmlDoc = new HtmlDocument();
htmlDoc.LoadHtml(html); var htmlNodes = htmlDoc.DocumentNode.SelectNodes("//body"); var htmlBody = htmlDoc.DocumentNode.SelectSingleNode("//body"); HtmlNode firstChild = htmlBody.FirstChild; Console.WriteLine(firstChild.OuterHtml);
LastChild:获取最后一个子节点,示例同上。
Descendants():返回所有后代节点:
var node = htmlDoc.DocumentNode.SelectSingleNode("//body");
foreach (var nNode in node.Descendants())
{
if (nNode.NodeType == HtmlNodeType.Element)
{
Console.WriteLine(nNode.Name);
}
}
Descendants(String):获取指定名称的后代节点:
var node = htmlDoc.DocumentNode.SelectSingleNode("//body");
foreach (var nNode in node.Descendants("h2"))
{
if (nNode.NodeType == HtmlNodeType.Element)
{
Console.WriteLine(nNode.Name);
}
}
属性
SetAttributeVaule设置节点属性:
var h1Node = htmlDoc.DocumentNode.SelectSingleNode("//h1");
h1Node.Attributes.Append("style");
h1Node.SetAttributeValue("style", "color:blue");
GetAttributeVaule获取节点属性:
如下例子中常用来在爬虫中获取音视频的url
var source = htmlDoc.DocumentNode.SelectSingleNode(@"//source[@type='audio/mpeg']");
var audioUrl = source.GetAttributeValue("src", "");
如下示例常用来在爬虫中获取title
var title = childHtmlDoc.DocumentNode.SelectSingleNode(@"//input[@name='title']").GetAttributeValue("value", "");
强大而灵活的的Html解析器——Html Agility Pack的更多相关文章
- [Swift通天遁地]一、超级工具-(18)创建强大、灵活的日期时间拾取器
★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★➤微信公众号:山青咏芝(shanqingyongzhi)➤博客园地址:山青咏芝(https://www.cnblogs. ...
- Solr Dismax查询解析器-深入分析
Solr 支持多种查询解析,给搜索引擎开发人员提供灵活的查询解析.Solr 中主要包含这几个查询解析器:标准查询解析器.DisMax 查询解析器,扩展 DisMax 查询解析器(eDisMax) Di ...
- DRF之解析器组件及序列化组件
知识点复习回顾一:三元运算 三元运算能够简化我们的代码, 请看如下代码: # 定义两个变量 a = 1 b = 2 # 判断a的真假值,如果为True,则将判断表达式的前面的值赋给c,否则将判断表达 ...
- 邵国际: C 语言对象化设计实例 —— 命令解析器
本文系转载,著作权归作者所有.商业转载请联系作者获得授权,非商业转载请注明出处. 作者: 邵国际 来源: 微信公众号linux阅码场(id: linuxdev) 内容简介 单片机工程师常常疑惑为什么 ...
- SpringMVC(一)概述、解析器与注解
个人博客网:https://wushaopei.github.io/ (你想要这里多有) 一.SpringMVC的概述 1.概述 Spring MVC框架是一个开源的Java平台,为开发强大的基 ...
- SQL解析器详解
1.概述 最近,有同学留言关于SQL解析器方面的问题,今天笔者就为大家分享一下SQL解析器方便的一些内容. 2.内容 2.1 SQL解析器是什么? SQL解析与优化是属于编辑器方面的知识,与C语言这类 ...
- 如何实现一个SQL解析器
作者:vivo 互联网搜索团队- Deng Jie 一.背景 随着技术的不断的发展,在大数据领域出现了越来越多的技术框架.而为了降低大数据的学习成本和难度,越来越多的大数据技术和应用开始支持SQL进 ...
- XML解析器(转)
常见C/C++ XML解析器有tinyxml.XERCES.squashxml.xmlite.pugxml.libxml等等,这些解析器有些是支持多语言的,有些只是单纯C/C++的.如果你是第一次接触 ...
- PHP Simple HTML DOM解析器
一直以来使用php解析html文档树都是一个难题.Simple HTML DOM parser 帮我们很好地解决了使用 php html 解析 问题.可以通过这个php类来解析html文档,对其中的h ...
随机推荐
- BZOJ2882工艺
题目描述 小敏和小燕是一对好朋友. 他们正在玩一种神奇的游戏,叫Minecraft. 他们现在要做一个由方块构成的长条工艺品.但是方块现在是乱的,而且由于机器的要求,他们只能做到把这个工艺品最左边的方 ...
- Ticwatch2_3G版省电优化
设置 --> 网络与连接 --> 云消息同步(禁用) 设置 --> 声音与震动 --> 铃声与音量(静音) 设置 --> 声音与震动 --> 闹钟音量(静音) 设置 ...
- 常用API接口签名验证参考
项目中常用的API接口签名验证方法: 1. 给app分配对应的key.secret2. Sign签名,调用API 时需要对请求参数进行签名验证,签名方式如下: a. 按照请求参数名称将所有请求参数按照 ...
- 第四十五篇--将文件写入SD卡
RAM: 运行内存 ROM: 外部存储,手机内部存储 SD卡:外部存储,SD卡存储. 在存储文件时千万不要忘记向清单文件中添加相应权限,并且android6.0以后还要添加运行时权限 还有一个权限有所 ...
- mysql 在visual studio中的配置
视图-->其他窗口-->服务器资源管理器-->数据连接-->右键添加连接 servername:localhost username:root password:123456 ...
- Java基础 -- Collection和Iterator接口的实现
Collection是描述所有序列容器(集合)共性的根接口,它可能被认为是一个“附属接口”,即因为要表示其他若干个接口的共性而出现的接口.另外,java.util.AbstractCollection ...
- easyui Datagrid 表格高度计算及自适应页面的实现
因为页面上既要计算表格的高度,又要自适应浏览器大小,之前都都采用固定表格高度,这样就会导致不同的分辨率电脑上看起来表格高矮不一, 所以采用了计算网页高度和其他div 的高度之差作为表格的初始高度: H ...
- Vue-router(基础)_滚动行为和history模式
一.前言 1.滚动事件 2.h5 history模式 二.主要内容 1. (1)使用前度路由,当切换到新路由时,想要页面滚动到顶部,或者是保持原先滚动的位置,就像重新加载页面那样.vue-rout ...
- Python并发编程之多线程使用
目录 一 开启线程的两种方式 二 在一个进程下开启多个线程与在一个进程下开启多个子进程的区别 三 练习 四 线程相关的其他方法 五 守护线程 六 Python GIL(Global Interpret ...
- JAVA 中的命名规则
命名规则– 基本要求• 见名知意– 常见命名的规则 • 包 (其实就是文件夹,用于对类进行管理)– 全部小写, 多级包用点隔开.– com,com.itheima • 类– 一个单词首字母大写 Stu ...