【转】 HtmlAgilityPack使用——XPath注意事项

【转】 HtmlAgilityPack使用——XPath注意事项

在使用HtmlAgilityPack这个开源的类库进行网页内容解析的时候是非常的方便(使用方法见另一篇博客《HTML解析:基于XPath的C#类库HtmlAgiliytyPack》),其基于XPath路径语法进行高效的选择文档节点,当发起请求获取了网页html文件的时候,解析的大部分工作量就落到了XPath路径表达式的书写了。本文测试在VS2010开发环境,.NetFramework
4.0 C#语言,使用的html如下:

<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
   <head>
 	<title>test</title>
   </head>
   <body>
     	<div id="content">
            <div>
				<a href="http://www.google.com">google</a>
				<div>gmail</div>
				<div>google earth</div>
            </div>
			<div>
				<a href="http://www.baidu.com">baidu</a>
			</div>
			<div>
				<a href="http://www.tmall.com">tmall</a>
			</div>
		</div>
   </body>
 </html>

1、HtmlAgilityPack节点类型

在使用XPath表达式选择文档特定节点的时候,我发现有时候按照上下文写出的路径表达式就是失效,或者选择出错到了错误的内容,或者由于SelectSingleNode或者SelectNodes这个两个函数使用相应的XPath表达式查询的时候找不到结果而跑出异常。后来发现,HtmlAgilityPack对节点的选择严格按照XPath的规范来实现,XPath规范中严格定义了七种类型的节点(http://www.w3school.com.cn/xpath/xpath_nodes.asp):元素(Element),属性(Attribute),文本(Test),命名空间,处理指令,注释,文档根节点。基本值是无父或无子的节点,项目(Item)是基本值或者节点,然后又父子、同胞、先辈和后辈这些关系。HtmlAgilityPack的每个HtmlNode对象就封装好了上述所有规范定义的项目,下图是一个节点对象包含的内容。

正是因为如此,在书写XPath路径表达式的时候需要考虑到HtmlAgilityPack将text也作为了一个node,因此对于我们一般意义上看到的html结构就要多考虑一次text节点,空的文本节点也算再内,这在javascript的IE下的一个特例就是如此,为此需要特别为IE浏览器而书写兼容的js代码。使用如下的C#代码输出的是空字符串,也就是空的text节点。

    HtmlDocument doc = new HtmlDocument();
            doc.Load(@"C:\test.html");
            HtmlNode main = doc.GetElementbyId("content");
            HtmlNode child = main.FirstChild;
            Console.WriteLine(child.InnerText);

以上结果输出为空:

这也就验证了,选取的为id为content的div节点的FirstChild节点是空的文本节点。因此对于FirstChild、LastChild、NextSibling、PrevSibling等关系表示的节点需要慎用,需要考虑空的text节点。

2、深刻理解“//”和“./”

XPath路径表达式中最关键的选择如下

表达式 描述
nodename 选取此节点的所有子节点。
/ 从根节点选取。
// 从匹配选择的当前节点选择文档中的节点,而不考虑它们的位置。
. 选取当前节点。
.. 选取当前节点的父节点。
@ 选取属性。

这也是书写路径表达式的基础,其中对于选择了一个节点之后,使用“//”和“./”这个两个语法总是会让人迷惑。本文实际测试了两者的区别。

  • “//”:从当前选择的节点开始寻找,对于后面的表达式是在当前节点中的任意位置寻找,只要符合的就加入到选择结果中。
  • “./”:也是从当前选择的节点开始选择,但是仅仅是寻找当前节点的直系子元素,而对于孙子及以后的节点都不考虑。

区别使用了如下的测试代码:

            HtmlDocument doc = new HtmlDocument();
            doc.Load(@"C:\test.html");
            HtmlNode main = doc.GetElementbyId("content");
            HtmlNodeCollection nodes = main.SelectNodes("./div");
            foreach (HtmlNode node in nodes)
            {
                Console.WriteLine("=============start=============");
                Console.WriteLine(node.InnerText);
                Console.WriteLine("=============end===============");
            }

上面输入结果如下:

使用如下代码继续测试:

            HtmlDocument doc = new HtmlDocument();
            doc.Load(@"C:\test.html");
            HtmlNode main = doc.GetElementbyId("content");
            HtmlNodeCollection nodes = main.SelectNodes("//div");
            foreach (HtmlNode node in nodes)
            {
                Console.WriteLine("=============start=============");
                Console.WriteLine(node.InnerText);
                Console.WriteLine("=============end===============");
            }

通过以上测试可以看出,根据路径表达式进行选择的时候需要进行特别区分出上述两者的区别,这样才能兼顾取得的结果是准确无误的。

            HtmlDocument doc = new HtmlDocument();
            doc.Load(@"C:\test.html");
            HtmlNode main = doc.GetElementbyId("content");
            HtmlNode node1 = main.SelectSingleNode("//div[1]/div[2]");
            HtmlNode node2 = main.SelectSingleNode("./div[1]/div[2]");
            Console.WriteLine(node1.InnerText);
            Console.WriteLine(node2.InnerText);

上述结果可以看出根据路径表达式选择的时候结果可能是一样的,因此需要依据具体情况对待。

以上是本人使用HtmlAgilityPack解析html过程中书写XPath表达式得出的一些认识,希望供有用过的朋友可以一起探讨交流。

时间: 2025-01-31 07:50:46

【转】 HtmlAgilityPack使用——XPath注意事项的相关文章

lxml结合xpath注意事项

使用Xpath语法,应该使用Element.xpath方法,来执行xpath选择,示例代码如下: trs = html.xpath("//tr[position()>2]") xpath函数返回的永远是一个列表 2.获取某个标签的属性: href = html.xpath("//a/@href") 3.获取文本 , 通过xpath下的text()函数: address = tr.xpath("./td[4]/text()")[0] 4.在某

C#+HtmlAgilityPack+XPath带你采集数据(以采集天气数据为例子)

转自原文C#+HtmlAgilityPack+XPath带你采集数据(以采集天气数据为例子) 阅读目录 1.HtmlAgilityPack简介 2.XPath技术介绍与使用 3.采集天气网站案例 4.资源 第一次接触HtmlAgilityPack是在5年前,一些意外,让我从技术部门临时调到销售部门,负责建立一些流程和寻找潜在客户,最后在阿里巴巴找到了很多客户信息,非常全面,刚开始是手动复制到Excel,是真尼玛的累,虽然那个时候C#还很菜,也想能不能通过程序来批量获取(所以平时想法要多才好).几

HtmlAgilityPack解析器在WP8.1下报错,不仅如此,社交化分享也报错。

以前WP7下是用的HtmlAgilityPack和 XPath来解析网页,很好用. 但是在Wp8.1下,这个里面却缺少了一个很重要的方法. 1 HtmlDocument doc = new HtmlDocument(); //实例化HtmlDocument对象 2 doc.LoadHtml(html); //载入HTML 3 var tags = doc.DocumentNode.SelectNodes("//li"); //根据HTML节点NODE的ID获取节点 SelectNode

HtmlAgilityPack开发

官方网站: http://html-agility-pack.net/ Nuget安装: Install-Package HtmlAgilityPack C# HTML Parser Examples: // From File var doc = new HtmlDocument(); doc.Load(filePath); // From String var doc = new HtmlDocument(); doc.LoadHtml(html); // From Web var url

使用C#和HtmlAgilityPack解析HTML

近期,有一个需求,需要解析HTML页面,读取一些需要的数据后,插入本地数据库.我知道可以通过正则表达式实现,然而正则表达式之于我,就像汇编语言之于我,一样.我知道它是干什么的,我也知道它能干什么,但是我一直不知道怎么干,曾经尝试过,后来用得太少,最终放弃了.也知道有一些组件可以实现操作HMTL,比如mshtml,比如WebBrowser,然而总是感觉不太好,不太专业.犹犹疑疑,一直没有开始,直到发现HtmlAgilityPack,如获至宝,中间那个词Agility,是敏捷.灵活的意思. 以下文字

XPATH 注入的介绍与代码防御

0x01 介绍 软件未正确对 XML 中使用的特殊元素进行无害化处理,导致攻击者能够在终端系统处理 XML 的语法.内容或命令之前对其进行修改.在 XML 中,特殊元素可能包括保留字或字符,例如“<”.“>”.“"”和“&”,它们可能用于添加新数据或修改 XML 语法.我们发现用户可控制的输入并未由应用程序正确进行无害化处理,就在 XPath 查询中使用.例如,假定 XML 文档包含“user”名称的元素,每个元素各包含 3 个子元素 -“name”.“password”和

C#HTML解析利器HtmlAgilityPack

HtmlAgilityPack是一个开源的解析HTML元素的类库,最大的特点是可以通过XPath来解析HMTL,如果您以前用C#操作过XML,那么使用起HtmlAgilityPack也会得心应手.目前最新版本为1.4.6,下载地址如下:http://htmlagilitypack.codeplex.com/ 目前稳定的版本是1.4.6,上一次更新还是2012年,所以很稳定,基本功能全面,也没必要更新了. 提到HtmlAgilityPack,就必须要介绍一个辅助工具,不知道其他人在使用的时候,是如

python基础一 ------xpath基础

xpath简介 1,使用路径表达式在xml和html中解析  2,包含标准函数路(所有库支持的xpath语法一致)      3,W3C标准 节点: 1 <body> 第一个节点: <html> 2 <a> <head> 与 <body>;<a> 与<div>;<h1>与<h2> 为同胞节点 3 <div> <h1> 是</span> 的父节点,同理<spa

爬虫神器XPath,程序员带你免费获取周星驰等明星热门电影

本教程由“做全栈攻城狮”原创首发,本人大学生一枚平时还需要上课,但尽量每日更新文章教程.一方面把我所习得的知识分享出来,希望能对初学者有所帮助.另一方面总结自己所学,以备以后查看. 可能看着文章很短,但大家想想高考时800字的作文用了多长时间.字都是一个字一个字的码出来的,也需要很多精力. 非常需要各位的支持,哪怕点个赞,评论一下.更多技术方向的文章可以关注我.力求写出高质量文章.帮助更多学习技术的人. 本人大学生一枚,如各位有Asp.Net和安卓开发方向的兼职,可以联系微信:cxx7177.感