标签:gravity 失效 padding 类库 nts get 验证 sha 出错
【转】 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>
在使用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节点。
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表达式得出的一些认识,希望供有用过的朋友可以一起探讨交流。
【转】 HtmlAgilityPack使用——XPath注意事项
标签:gravity 失效 padding 类库 nts get 验证 sha 出错
原文地址:http://www.cnblogs.com/coky/p/6754812.html