为什么这个看似简单的Xpath导航无法正常工作?

时间:2013-08-21 17:12:01

标签: c# html xpath

我有一个看起来很简单的问题。我试图通过Xpath导航到HTML中的元素,似乎无法让它正常运行。

我想从页面的html内容中获取一个范围。页面相当复杂,所以我一直在使用Firebug的“通过xpath获取元素”并将结果粘贴到我的代码中。我注意到它与你在Chrome中做同样事情所获得的xpath略有不同,但它们似乎都指向同一个地方。

我正在尝试浏览的html是found here。我试图通过xpath访问的字段是第一个“ n 的结果1 - 10”。

基于FireBug的'inspect element',xpath应为:/html/body/div/center/table/tbody/tr[6]/td/table/tbody/tr/td[2]/table/tbody/tr/td/table/tbody/tr/td/table/tbody/tr/td/table/tbody/tr/td/span

但是,当我尝试使用此xpath来识别C#代码隐藏中的元素时,它会给我一些错误,指出无法找到该路径。

我在这里做错了吗?我已经尝试了一些xpath的排列,我不明白为什么这不会在代码中合作。

编辑:我在HTMLAgilityPack中遇到此问题(但设法使用正则表达式来破解错误的解决方案)和在回答found here之后建模的SELECT语句

编辑2:我正在尝试使用Yahoo的免费代理来解决这个问题,如示例here中所示:

var query = 'SELECT * FROM html WHERE url="http://mattgemmell.com/2008/12/08/what-have-you-tried/" and xpath="//h1" and class="entry-title"';
var url = "http://query.yahooapis.com/v1/public/yql?q=" + query + "&format=json&callback=??";


$.getJSON(url,function(data){
    alert(data.query.results.h1.content);
})

我遇到了与HTML敏捷包相同的问题,但我更感兴趣的是让这部分工作。它适用于回答者给我的提供的URL(见上文)。但是,当我尝试在http://nl.newsbank.com url上使用简单的xpath表达式时,无论xpath的基本程度如何,我都会收到每次都没有检索到对象的错误。

编辑3:我认为我会详细说明我正试图解决的更大问题的大局,这个问题是一个关键组成部分,希望它可能提供更多的洞察力。< / p>

为了从头开始学习基本的ASP.NET开发技能,我决定基于http://nl.newsbank.com/的新闻档案搜索创建一个简单的Web应用程序。在当前的迭代中,它发送一个POST请求(尽管我现在已经知道你可以使用GET请求,只是在URL的末尾转储正文)来发送搜索条件,就像用户在搜索栏中输入条件一样。然后它搜索响应(使用RegExes,而不是Xpath,因为我无法使其工作),用于 n “span的结果1- n ,提取 n < / em>,并将其转储到表中。这是一个很酷的小工具,用于查找新闻发生率。

我想添加一些功能,以便您可以输入日期范围(例如2002年5月 - 2010年6月),并针对该范围内的每个月/周运行频率搜索。这在概念上很容易实现。然而问题是,现在所有这些都发生在服务器端,并且由于没有API,HTTP响应包含整个页面,因此是非常带宽的。一次发送数十个查询会吞下绝对无法形容的带宽量,甚至不会有一点可扩展性。

结果我尝试重写应用程序以在客户端工作。但是由于same-origin policy我无法从客户端向外部主机发送请求。但是,我有一个漏洞,我可以使用免费的Yahoo代理发出请求并将其转换为JSON,然后我可以使用Same-Origin策略的JSON异常从代理中检索该数据。

这是我遇到特定于http://nl.newsbank.com的这些xpath问题的地方。我无法使用任何xpath检索html,我不确定为什么或如何修复它。在VS2010中进行调试时,我会收到错误Microsoft JScript runtime error: Unable to get value of the property 'content': object is null or undefined

3 个答案:

答案 0 :(得分:1)

您的示例HTML页面的元素没有很多可供选择的类,但如果您对包含“结果:1 - 10 of n”的第一个<span>元素感兴趣,则可以使用XPath明确定位此文本内容的表达式。

例如:

//table//span[starts-with(., "Results:")]

将选择<span>中包含的所有<table>元素,其中包含以“结果:”开头的文字(我认为//table在您的情况下并非绝对必要,但不妨限制一点)

您想要这些<span>中的第一个,因此您可以使用此表达式:

(//table//span[starts-with(., "Results:")])[1]

请注意前一个表达式周围的括号,然后 [1]选择与文本匹配的所有<span>中的第一个

答案 1 :(得分:1)

保佑。已经在评论中提到过,TBODY元素是由webkit引擎生成的。下一个问题是默认情况下页面上不存在BODY和CENTER之间的DIV。它在第119行的JS声明中添加。

剥离DIV和TBODY元素后,如

  

/ HTML /体/中心/表/ TR [6] / TD /表/ TR / TD [2] /表/ TR / TD /表/ TR / TD /表/ TR / TD /表/ TR / TD /跨度

我可以使用HthmlAgilityPack成功选择一个节点。

编辑:不要使用像Firebug这样的工具来获取网站上的XPath值。如果你只是想看看页面的来源,甚至不要使用它。 Firebug的问题是,它会显示当前 DOM文档树,几乎每个文档树都可能已被(严重)修改过JS。

答案 2 :(得分:0)

这可能听起来有点简单,但您正在寻找的元素是唯一使用css类“basic-text-white”的doc元素。我认为这比查找长xpath要容易得多。网络抓取从来都不是一件稳定的事情,但我认为这可能和xpath一样稳定。尝试调试xpath只是让我的眼睛流血。