【问题标题】:Why is this seemingly simple Xpath navigation not working?为什么这个看似简单的 Xpath 导航不起作用?
【发布时间】:2013-08-24 04:40:47
【问题描述】:

我遇到了一个看起来非常简单的问题。我正在尝试通过 Xpath 导航到 HTML 中的元素,但似乎无法使其正常运行。

我想从页面的 html 内容中获取一个跨度。该页面相当复杂,因此我一直在使用 Firebug 的“通过 xpath 获取元素”并将结果粘贴到我的代码中。我注意到它与您在 Chrome 中执行相同操作所获得的 xpath 略有不同,但它们似乎都指向同一个地方。

我要导航的 html 是 found here。我试图通过 xpath 访问的字段是第一个“n 的结果 1 - 10”。

基于 FireBug 的“检查元素”,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:我想我会更详细地阐述我正在尝试解决的更大问题的大图,这个问题是一个关键组成部分,希望它可能提供更多的洞察力。

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

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

因此,我尝试重写应用程序以在客户端工作。但是由于same-origin policy,我无法从客户端向外部主机发送请求。但是有一个漏洞,我可以使用免费的 Yahoo 代理发出请求并将其转换为 JSON,然后我可以使用同源策略的 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

【问题讨论】:

  • 页面有多个 IFrame。根据您使用的技术,它可能需要一点“推动”来处理 IFrame。你用的是什么技术? LINQ2XML? HtmlAgilityPack?硒?瓦廷?
  • HtmlAgilityPack 和一个 SELECT 语句都以编辑中的链接答案为模型(我并不复杂地理解代码,但似乎在示例中有效)
  • 尝试删除表达式中的tbody 元素。 tbody 元素通常由 Firefox 或 Chrome 添加,前提是它们没有出现在源 HTML 中 tr 之前。所以像/html/body/div/center/table/tr[6]/td/table/tr/td[2]/table/tr/td/table/tr/td/table/tr/td/table/tr/td/span 这样的东西可能会起作用。或者更安全/html/body/div/center/table//tr[6]/td/table//tr/td[2]/table//tr/td/table//tr/td/table//tr/td/table//tr/td/span
  • 谢谢,我试试看。
  • 关于 Html Agility Pack:在线上的 HTML(库通常使用的那个)和浏览器的内存 DOM 之间可能存在巨大差异,因为第二个可能是完全由客户端javascript创建。否则,恕我直言,您不应该像您展示的那样使用 XPATH(这 不是 简单的 XPATH),这是厄运的秘诀。 HTML 上的 XPATH 表达式应针对唯一的最小判别元素进行定制。调试工具提供的 XPATH 几乎无法使用。您应该改用 thinks lile //td[@class='blabla']//span[@id='blabla'

标签: c# html xpath


【解决方案1】:

正如保罗。已经在评论中提到,TBODY 元素是由 webkit 引擎生成的。接下来的问题是页面上默认不存在BODY和CENTER之间的DIV。它是由第 119 行的 JS 语句添加的。

在去掉 DIV 和 TBODY 元素之后

/html/body/center/table/tr[6]/td/table/tr/td[2]/table/tr/td/table/tr/td/table/tr/td/table/tr/时差/跨度

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

编辑:不要使用 Firebug 之类的工具在网站上获取 XPath 值。如果您只想查看页面的来源,甚至不要使用它。 Firebug 的问题在于,它会向您显示 当前 DOM 文档树,它可能几乎在每个文档树上都已经(大量)被 JS 修改了。

【讨论】:

  • 在选择节点时遇到了一些模棱两可的问题,我将继续查看,但实际上它正在获取内容!非常感谢,恭喜你。
  • 没关系,它似乎仍然因为第一个原因而受到影响。我会更详细地研究它。
【解决方案2】:

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

例如:

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

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

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

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

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

【讨论】:

  • 这适用于我的示例 URL,但不适用于我尝试使用的 URL。如果您不介意,请查看我的最新编辑
  • 我尝试搜索的新闻银行 URL 已链接到问题中
【解决方案3】:

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

【讨论】:

  • 我想到了。除了元素出现两次(尽管内容相同,因此不难解决)这一事实之外,我无法让它与 Nl.newsbank 链接一起使用,即使在其他示例中似乎也是如此.看看我的最新编辑。
  • 我直接从网络中获取了上下文(即不是浏览器解释的那样,只是原始的 http 结果)。将原始文本视为字节流,并根据“basic-text-white”手动将其切碎,根本没有理由进行 XML 解析。这样看起来很容易。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-12-06
  • 2011-10-25
  • 2012-06-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多