最近处于毕业设计开始阶段,前期工作需要去国外的一些专业数据库网站比对一些所需TF家族信息,为了快捷方便,想到用程序去帮助实现。前期实现了一系列的尝试,使用C#的的网络编程类库,获取查询结果,但是为了分析其中的结果并进行比对,我最开始尝试了两天之久的正则表达式,最后发现在解析这样的HTML文档的时候,花费时间太多,因此开始改变策略,最后得知MSHTML和HAP这两个.NET解析html的类库,出于对HAP这个轻量级类库兴趣,决定使用它来解析获取信息。
一、HAP简介
HAP是codeplex公司的一个解析html的.NET开源项目,支持XPath查询。官网(http://htmlagilitypack.codeplex.com/)给出的介绍是:
What is exactly the Html Agility Pack (HAP)?
This is an agile HTML parser that builds a read/write DOM and supports plain XPATH or XSLT (you actually don't HAVE to understand XPATH nor XSLT to use it, don't worry...). It is a .NET code library that allows you to parse "out of the web" HTML files. The
parser is very tolerant with "real world" malformed HTML. The object model is very similar to what proposes System.Xml, but for HTML documents (or streams).
目前最新版本为HAP1.4.6,推出的新特性是支持Linq语言。
二、XPath
为了更好的使用HAP,必须了解XPath语言。维基百科介绍如下:
XPath即为XML路径语言(XML Path Language),它是一种用来确定XML文档中某部分位置的语言。
XPath基于XML的树状结构,提供在数据结构树中找寻节点的能力。起初XPath的提出的初衷是将其作为一个通用的、介于XPointer与XSL间的语法模型。但是XPath很快的被开发者采用来当作小型查询语言。
XPath中,有七种类型的节点:元素、属性、文本、命名空间、处理指令、注释、根节点。节点关系有:Parent、Children、Sibling、Ancestor、Descendent。
路径表达式用来选取节点或节点集,通过路径(path)或步(steps)进行选取。
节点表达式:
表达式
描述
nodename |
选取此节点的所有子节点。 |
/ |
从根节点选取。 |
// |
从匹配选择的当前节点选择文档中的节点,而不考虑它们的位置。 |
. |
选取当前节点。 |
.. |
选取当前节点的父节点。 |
@ |
选取属性。 |
路径表达式
结果
bookstore |
选取 bookstore 元素的所有子节点。 |
/bookstore |
选取根元素 bookstore。
注释:假如路径起始于正斜杠( / ),则此路径始终代表到某元素的绝对路径!
|
bookstore/book |
选取属于 bookstore 的子元素的所有 book 元素。 |
//book |
选取所有 book 子元素,而不管它们在文档中的位置。 |
bookstore//book |
选择属于 bookstore 元素的后代的所有 book 元素,而不管它们位于 bookstore 之下的什么位置。 |
//@lang |
选取名为 lang 的所有属性 |
谓语:用来查找某个特定的节点或者包含某个指定的值的节点。谓语被嵌在方括号中
路径表达式
结果
/bookstore/book[1] |
选取属于 bookstore 子元素的第一个 book 元素。 |
/bookstore/book[last()] |
选取属于 bookstore 子元素的最后一个 book 元素。 |
/bookstore/book[last()-1] |
选取属于 bookstore 子元素的倒数第二个 book 元素。 |
/bookstore/book[position()<3] |
选取最前面的两个属于 bookstore 元素的子元素的 book 元素。 |
//title[@lang] |
选取所有拥有名为 lang 的属性的 title 元素。 |
//title[@lang='eng'] |
选取所有 title 元素,且这些元素拥有值为 eng 的 lang 属性。 |
/bookstore/book[price>35.00] |
选取 bookstore 元素的所有 book 元素,且其中的 price 元素的值须大于 35.00。 |
/bookstore/book[price>35.00]/title |
选取 bookstore 元素中的 book 元素的所有 title 元素,且其中的 price 元素的值须大于 35.00。 |
通配符:
通配符
描述
* |
匹配任何元素节点。 |
@* |
匹配任何属性节点。 |
node() |
匹配任何类型的节点。 |
选取多个路径时,使用 “ | ”符号。
步(Step):语法为 轴名称::节点测试[谓语]
轴(axis)-------------------------------定义所选节点与当前节点之间的树关系
节点测试(node-test)----------------识别某个轴内部的节点
零个或多个谓语(predicate)--------更深入提炼所选的节点集
XPath轴:
轴名称
结果
ancestor |
选取当前节点的所有先辈(父、祖父等)。 |
ancestor-or-self |
选取当前节点的所有先辈(父、祖父等)以及当前节点本身。 |
attribute |
选取当前节点的所有属性。 |
child |
选取当前节点的所有子元素。 |
descendant |
选取当前节点的所有后代元素(子、孙等)。 |
descendant-or-self |
选取当前节点的所有后代元素(子、孙等)以及当前节点本身。 |
following |
选取文档中当前节点的结束标签之后的所有节点。 |
namespace |
选取当前节点的所有命名空间节点。 |
parent |
选取当前节点的父节点。 |
preceding |
选取文档中当前节点的开始标签之前的所有节点。 |
preceding-sibling |
选取当前节点之前的所有同级节点。 |
self |
选取当前节点。 |
XPath可以使用运算符:
运算符
描述
实例
返回值
| |
计算两个节点集 |
//book | //cd |
返回所有拥有 book 和 cd 元素的节点集 |
+ |
加法 |
6 + 4 |
10 |
- |
减法 |
6 - 4 |
2 |
* |
乘法 |
6 * 4 |
24 |
div |
除法 |
8 div 4 |
2 |
= |
等于 |
price=9.80 |
如果 price 是 9.80,则返回 true。
如果 price 是 9.90,则返回 false。
|
!= |
不等于 |
price!=9.80 |
如果 price 是 9.90,则返回 true。
如果 price 是 9.80,则返回 false。
|
< |
小于 |
price<9.80 |
如果 price 是 9.00,则返回 true。
如果 price 是 9.90,则返回 false。
|
<= |
小于或等于 |
price<=9.80 |
如果 price 是 9.00,则返回 true。
如果 price 是 9.90,则返回 false。
|
> |
大于 |
price>9.80 |
如果 price 是 9.90,则返回 true。
如果 price 是 9.80,则返回 false。
|
>= |
大于或等于 |
price>=9.80 |
如果 price 是 9.90,则返回 true。
如果 price 是 9.70,则返回 false。
|
or |
或 |
price=9.80 or price=9.70 |
如果 price 是 9.80,则返回 true。
如果 price 是 9.50,则返回 false。
|
and |
与 |
price>9.00 and price<9.90 |
如果 price 是 9.80,则返回 true。
如果 price 是 8.50,则返回 false。
|
mod |
计算除法的余数 |
5 mod 2 |
1 |
XPath有一百多个函数,常用在谓语中选择的函数有
position() 表示当前节点的序号
last() 表示取最后一个节点
name() 表示当前节点名字
在.NET中可以使用XPath处理XML文档,此处的html解析就是运用XPath查询选择。
三、HAP使用
1、下载HtmlAgilityPack最新压缩包,http://htmlagilitypack.codeplex.com/releases/view/90925,官方下载地址。
2、加压后,在所需项目中添加引用HtmlAgilityPack.dll文件,其中还附带了xml文件用于文档说明。然后添加using HtmlAgilityPack说明。如下图所示:
3、实际使用中,都是以HtmlDocument类为主线。HAP提供了两种不同方式加载HtmlDocument类的实例:从html字符串构造(可以使用LoadHtml方法和Load方法),从html文档流构造实例(使用Load方法)。从而就可以实例化一个DOM实例,对于客户端脚本语言JavaScript熟悉的开发者来说这是非常熟悉的。这些操作也与.net framework中的XmlDocument类对于XML文档的操作非常类似,而且XML操作中也支持使用XPath表达式的查询使用,不同的是HtmlDocument强化了GetElementById方法,可以直接使用定位。示例代码如下:
HtmlDocument hd = new HtmlDocument();
hd.LoadHtml(fileStr);
HtmlNode root = hd.DocumentNode;
HtmlNodeCollection hNodes = root.SelectNodes("//tr[@class='odd']|//tr[@class='even']/td[@class='rowNum']");
4、后续的使用需要依照自己的实际需求来设计。对于html文档的解析主要就是使用XPath表达式进行选择定位,可以参考http://www.w3school.com.cn/xpath/xpath_syntax.asp。
5、去除script和style等标签。当使用document.DocumentNode.InnerText获取文档内容时会包含script等标签,因此可以使用下面的方法去除:
foreach(var script in doc.DocumentNode.Descendants("script").ToArray())
script.Remove();
foreach(var style in doc.DocumentNode.Descendants("style").ToArray())
style.Remove();
foreach(var comment in doc.DocumentNode.SelectNodes("//comment()").toArray())
comment.Remove();
6、在下载的HtmlAgilityPack压缩包中还找到了关于WindowsPhone开发需要的dll文件,因此对于开发WP手机应用也是非常的有效。
HtmlAgilityPack对于html页面的解析、信息采集的准确度和效率都优于使用正则表达式,而且对开发者非常友好,特别是正则表达式的学习曲线较陡,而且其中包含了很多的技巧,特别是对高效的正则表达式的书写是非常需要经验的。HtmlAgilityPack获取html文档时对原文本的结构要求是非常宽松的,这与XmlDocument的严格要求是不同的。基本上熟悉了XPath的语法之后,大部分应用都可以满足要求了。
参考资料:
1、HAP:简单好用的html解析器:http://msdn.microsoft.com/zh-tw/ee787055.aspx
2、XPath维基百科:http://zh.wikipedia.org/zh-cn/XPath
3、W3C school:http://www.w3school.com.cn/xpath/xpath_syntax.asp
4、C#:HtmlAgilityPack extract inner text:http://stackoverflow.com/questions/2785092/c-htmlagilitypack-extract-inner-text
分享到:
相关推荐
HtmlAgilityPack是.net下的一个HTML解析类库。支持用XPath来解析HTML。这个意义不小,为什么呢?因为对于页面上的元素的xpath某些强大的浏览器能够直接获取得到,并不需要手动写。节约了大半写正则表达式的时间,...
JsoupXpath 是一款纯Java开发的使用xpath解析html的解析器,xpath语法分析与执行完全独立,html的DOM树生成借助Jsoup,故命名为JsoupXpath.为了在java里也享受xpath的强大与方便但又苦于找不到一款足够强大的xpath...
基于 XPath 查询的分层、异构、应用程序数据建模和数据绑定库。 该库旨在允许将数据源(例如关系数据库、文档数据库、文件系统、网络服务器等)的异构集合统一到一个可以查询和查询的分层应用程序数据模型中。使用 ...
crystal-html5:具有XPath和CSS选择器支持HTML5兼容标记器和解析器的Crystal实现
用dom4j解析xml时,经常需要用到xpath,由于dom4j-1.6.1.jar不包括jaxen-1.1-beta-6.jar,导致使用xpath报错。 其中jaxen-full.jar是为了解决ava.lang.NoClassDefFoundError: org/jaxen/JaxenException错误。 下载的...
Harser:对HTML解析和构建XPath的简单方法
Xpath生成器,自动生成可用的Xpath
xPath.jar,XML解析包。XPath是获取xml中数据的一种方式,其简单语法易用。
Gammo-纯Ruby HTML5解析器 Gammo提供了纯Ruby HTML5兼容的解析器和XPath支持,以遍历Gammo构建的DOM树。 Gammo中HTML5解析算法的实现符合。给定一个HTML字符串,Gammo将基于WHATWG解析算法中定义的标记化和树构建...
xxxpwn : XPath 过滤扩展工具 : 专为盲优化 XPath 1 注入攻击而设计 xxxpwn 使用各种 XPath 优化来查询来自存在 XPath 注入的位置提供的后端 XML 文档的自定义信息。 默认情况下,它会尝试检索整个远程数据库,尽管...
html2xpath 通过XPath遍历给定的URL,并将选定的元素作为JSON返回。 用法 范围 必需的 描述 ü 是的 网页的URL,以执行给定的XPath查询。 x [ n ] 是的 要执行的XPath查询。 您可以在单个请求中运行多个XPath...
此算法实现是基于Xpath的xml文件查询,只要输入Xpath路径(全路径)就能返回目标节点信息,同时也支持数据的更新设置。
用来解析HTML代码,从中提取有用的信息。类似于网络检索
欢迎使用XPath下一页 这是W3C XPath Next Community Group的github项目: : XPath Next是一个收集来自以下方面的XPath标准演进需求的地方: XPath规范 ( ) , ( ) , 以及 , ( )和 , ( EBNF语法)...
XPath XPath,全称 XML Path Language,即 XML 路径语言,它是一门在 XML 文档中查找信息的语言。最初是用来搜寻 XML 文档的,但同样适用于 HTML 文档的搜索。所以在做爬虫时完全可以使用 XPath 做相应的...
xpath: 是一门在xml 文档中查找信息的语言,这里,我们可以用xpath来查找html文档,它是一种路径表达式 常用的路径表达式: 表达式 含义 // 不考考虑位置的查找 ./ 从当前节点开始往下查找 . . ...
C# 写的测试XPath 的小工具,用来测试写的Xpath 是否正确
根据报告中每条失效脚本的XPath和value信息,通过遍历新旧应用网页差异文档对象化模型解析树(DOM tree),找到替换失效脚本的路径或value值,从而修复失效的测试脚本。实验结果表明,该方法对修复失效测试脚本是...
将XPath命令添加到测试运行程序 用npm安装 npm install -D cypress-xpath 用纱安装 yarn add cypress-xpath --dev 然后将其包含在您项目的cypress/support/index.js require ( 'cypress-xpath' ) 使用 安装后,您的...
C#写的XPath解析工具