4

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

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

我正在尝试导航的 html 可在此处找到。我试图通过 xpath 访问的字段是第一个“Results 1 - 10 of n ”。

基于 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 中遇到了这个问题(但设法改用正则表达式破解了一个糟糕的解决方案)和一个 SELECT 语句以此处找到的答案为模型

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

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 的末尾)来发送搜索条件,就好像用户在搜索栏中输入了条件一样. 然后它在响应中搜索“Results 1- n of n ”跨度(使用 RegExes,而不是 Xpath,因为我无法让它工作),提取n并将其转储到表中。这是一个很酷的小工具,用于查找一段时间内的新闻发生率。

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

结果,我尝试重写应用程序以在客户端工作。但是,由于同源策略,我无法从客户端向外部主机发送请求。但是有一个漏洞,我可以使用免费的 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

4

3 回答 3

1

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

例如:

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

will select all <span> elements, contained in a <table>, and that contain text beginning with "Results:" (the //table is not strictly necessary in your case I think, but might as well restrict a little)

You want the first one of these <span>, so you can use this expression:

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

Note the brackets around the whole previous expression and then [1] to select the first of all the <span> matching the text

于 2013-08-26T11:17:29.950 回答
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/td/span

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

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

于 2013-08-30T15:26:24.133 回答
0

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

于 2013-08-23T20:56:51.387 回答