【问题标题】:XPath expression to add to code that already finds cities, that might also retrieve nearby zip codesXPath 表达式添加到已经找到城市的代码中,也可能检索附近的邮政编码
【发布时间】:2014-08-13 22:17:36
【问题描述】:

经过大量手动工作,我创建了 XPath 表达式,可以从解析的网站 HTML 中检索近 100 家公司在其中设有办事处的城市。到了很晚,我才恍然大悟,这些城市的邮政编码会非常出色且与众不同。

我意识到没有任何一条额外的 XPath 代码可以涵盖所有情况,但是是否有一些通用表达式可以合理地经常在同一行或附近检索 5 个数字(或 5 个数字、一个连字符和 4 个数字)命名空间[假设邮政编码在城市之后]?

例如代码

//div[@class='content']//h5

可能会添加类似"and \\d{5}" [我不擅长 XPath,并且正在使用带有反斜杠的 R 正则表达式语法 5 位且只有 5 位数字]。然后我可以快速粘贴附加代码,看看它是否带回邮政编码,其余的由手工完成。

回应评论:

这是数百个 HTML 代码之一:

<div class="container">
<script type="text/javascript">
<div class="header">
<table>
<tbody>
<tr>
<td class="bodywrap" valign="top">
<table width="100%" cellspacing="0" cellpadding="0" border="0">
<table class="body" width="100%" cellspacing="0" cellpadding="20" border="0">
<tbody>
<tr>
<td>
<table class="body" width="100%" cellspacing="3" cellpadding="0" border="0">
<tbody>
<tr valign="top">
<td width="50%">
<table width="100%" cellspacing="0" cellpadding="0">
<img border="0" src="/files/Office/ac28ef17-906a-4ed0-9850-0af853da6abe/Presentation/ceOfficeNameImage/t_NewYork.gif">
<br>
<br>
1251 Avenue of the Americas
<br>
New York, New York 10020
<br>
T:
<span class="skype_c2c_print_container notranslate">212.262.6700</span>

我已经尝试过这个 XPath 表达式,但没有成功。即使要提取“纽约”,我也希望能够提取“10020”。

我在带有 XML 1.0 的 Windows 8 上(根据 2013 SO 帖子,没有 XML 2.0)。

回应评论: 这是我使用的代码示例。

doc <- htmlTreeParse("http://www.butlersnow.com/Contact_Us.aspx", useInternal = TRUE)
xpathSApply(doc, "//div[@class='content']//h5", xmlValue, trim = TRUE)

【问题讨论】:

  • XPath 1.0 还是 2.0?您现有的 XPath 表达式是什么样的? HTML 是什么样的?
  • systemInfo() 说我正在运行其他附加包:[1] XML_3.98-1.1。我确实在问题中展示了一个 XPath 表达式;大约有 65 种变体——遍布整个地图。同样,HTML 因公司而异。该问题询问如何将 XPath 表达式添加到已找到地址节点的现有表达式中。
  • 什么是“附近的命名空间”?您在什么环境中使用 XPath?我们需要查看 XPath 嵌入到 HTML 示例中的代码,而且至关重要的是。你如何期望任何人添加到未知的东西?
  • 我添加了一个例子。我的术语可能在“附近的命名空间”上是错误的,但我认为这意味着返回城市的节点——所以地址的邮政编码很可能是“附近的”。
  • 我很抱歉这么厚。我相信我的 XPath 来自 XML 的 R 程序版本。我编辑了问题以放入我的代码示例。

标签: xml r xpath


【解决方案1】:

所以,我们已经发现你了

  • 在 R 中使用提供 HTML 解析和 XPath 功能的包
  • 正在寻找从 HTML 文本内容中挑选出特定字符序列的 XPath 表达式

我们还没有确定 R 语言中这个模块支持 XPath 的哪个版本。它要么只符合 XPath 1.0 标准(更有可能),要么也支持 XPath 2.0。

为什么这是相关的?这是相关的,因为only XPath 2.0 提供了可以处理正则表达式的函数。正则表达式可以解决您描述的问题,即在任意字符串中连续查找 5 个数字。现在,您如何确定支持哪个版本?只需使用仅在 XPath 2.0 中可用的函数,例如 tokenize(),看看这是否会引发错误。

选项 1:这个 R 功能支持 XPath 2.0

首先,确定可能包含邮政编码的元素。例如,假设它位于h5element 内。然后,将matches() 函数与正则表达式一起使用。

//h5[matches(.,'\d{5}')]

或者这个的轻微变化。当然,R 无法区分实际的邮政编码和其他仅由五位数字组成的事物。

选项 2:只有 XPath 1.0 可供您使用

然后,在我看来,没有合理的方法将它组合成一个 XPath 表达式,因为正则表达式不可用。但是,R 本身恰好是good at regular expressions。使用 XPath 从 HTML 中提取所有相关字符串,然后在 XPath 之外的 R 中使用正则表达式搜索它们。


注意:所有这些都不能以任何方式“证明”像这样简单的正则表达式足够精确和限制性足以仅查找邮政编码。在大量 HTML 文档中,可能存在很多无法与“真实”命中区分开来的“误报”。然后,您必须改进方法,例如对照邮政编码数据库检查结果。

由于我还是在写,所以没有“附近的命名空间”之类的东西。您将 XPath 中称为 context item 的内容误认为是命名空间。在以下示例中,http://www.ns.com 是一个命名空间。

<ns:root xmlns:ns="http://www.ns.com">
  <ns:a/>
</ns:root>

【讨论】:

  • +1,很好的答案。我同意 R 的“XML”包很可能只支持 XPath 1.0。我找到的文档 (cran.r-project.org/web/packages/XML/XML.pdf) 似乎没有明确说明,但它确实引用了 XPath 1.0 (w3.org/TR/xpath) 的规范。
  • 那太好了,@Mathias Muller。谢谢你。由于我尝试了 tokenize() 并得到了错误:找不到函数“tokenize”,所以我必须使用 XPath 1.0。我看了一遍,但找不到如何安装 XPath 2.0。我之前安装了 XML 包。我去了 WEC3(如果是这个名字的话),但是我找不到 XPath 2.0 下载选项。是在github上吗?抱歉这么幼稚,我尊重你的时间和注意力。
  • @lawyeR 欢迎您。很可能根本没有在 R 中实现 XPath 2.0,仅仅是因为没有人实现它——那么你必须使用 1.0 版本并在我的回答中坚持使用选项 2。 (P.S. 名称是“W3C” :-)
  • @lawyeR:仅供参考,W3C 为 XPath(和其他技术)的行为方式制定标准(规范,也称为“建议”),但不开发或发布实现。
猜你喜欢
  • 1970-01-01
  • 2013-07-24
  • 2010-09-30
  • 1970-01-01
  • 2012-01-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-12-24
相关资源
最近更新 更多