【问题标题】:XPath: find <dd> sibling elements between two <dt> elements which are also siblingsXPath:在同为兄弟的两个 <dt> 元素之间查找 <dd> 兄弟元素
【发布时间】:2020-08-29 21:46:50
【问题描述】:

我有这个结构:

<dl>
  <!-- preceded by a variable amount of <dt> and <dd> nodes -->
  <dt>Venues</dt>
  <dd>Madison Square Garden</dd>
  <dd>Wembley</dd>
  <!-- there could be more venues (in <dd>) here -->
  <!-- the following <dt> doesn't necessarily have to contain text "Event" - it can be something else, too -->
  <dt>Event</dt>
  <dd>Grand opening</dd>
  <dt>Series</dt>
  <dd>Golden Virginia 49</dd>
  <!-- a variable amount of <dt> and <dd> nodes continues -->
</dl>

我正在尝试在浏览器上下文(即 Javascript)中提取 Venues

  • 麦迪逊广场花园
  • 温布利

我该怎么做?

我最接近的尝试是:

$x("//dt[text()='Venues']/following-sibling::dd")

...但这让我得到了所有&lt;dd&gt; 元素,而我试图在&lt;dt&gt; 和@ 的数量的情况下在两个&lt;dt&gt; 元素之间获取&lt;dd&gt; 元素987654328@ 元素是可变的,我相信并且我可能错了,排除了使用count()

【问题讨论】:

  • 你提到“
    Event
    ”;那&lt;dt&gt; 是空的还是有其他文字?
  • 我想说的是&lt;dt&gt;Venues&lt;/dt&gt;之后的&lt;dd&gt;元素后面的&lt;dt&gt;Venues&lt;/dt&gt;不必包含文本“事件”

标签: javascript html xpath web-scraping


【解决方案1】:

所以我相信要在各种dt 标签之间提取dd 标签,您将不得不使用一些稍微不同的xpath,利用following-siblingpreceding-sibling

要获取包含“场地”信息的 dd 标签,您可以使用以下 xpath:

//dt[contains(text(), 'Venues')]/following-sibling::dt[contains(text(), 'Event')]/preceding-sibling::dd/text()

这个 xpath 首先关注包含文本“Venues”的dt 标记。然后,它关注以下包含文本“事件”的兄弟dt 标签。然后查找当前路径之前的所有dd 标签,为您提供:

  • 麦迪逊广场花园
  • 温布利

但是,您不能使用此 xpath 来获取“事件”的信息,方法是将 dt 包含文本替换为“事件”和“系列”,就像在第一个 xpath 中完成的那样。这给出了您注意到的相同问题,您得到的 dd 标签比您想要的要多。你现在必须使用这个 xpath:

//dt[contains(text(), 'Event')]/following-sibling::dt[contains(text(), 'Series')]/preceding-sibling::dd[preceding-sibling::dt[contains(text(), 'Event')]]/text()

这里,“系列”dt 标记的前同级 dd 标记本身必须有一个前同级,即包含文本“事件”的 dt 标记。这给了你:

  • 盛大开幕

要获取'Series'下的dd标签(dl父节点中包含的最后一个dt标签,那么你可以利用你原来厌倦的xpath)。

希望这会有所帮助。你走在正确的道路上。有时必须进行大量的试验和错误才能找到您尝试命中的节点。

【讨论】:

  • 事实上,您实际上可以忽略帖子中的第一个 xpath,而只使用第二个。这应该适用于所有具有前后 dt 标记的 dd 标记。它只是最后一个 dd 标记,然后您将使用您尝试使用的原始 xpath
【解决方案2】:

假设每个&lt;dl&gt;只有一个&lt;dt&gt;Venues&lt;/dt&gt;和一个其他&lt;dt&gt;,并且这两个&lt;dt&gt;s按顺序出现在&lt;dl&gt;中,下面的xpath应该得到所有的场地@987654326 @s 不管有多少:

//dl//dd[preceding-sibling::dt[.="Venues"]][not(preceding-sibling::dt[not(.="Venues")])]

【讨论】:

  • 不幸的是,它不起作用 - 我得到一个空的结果集。一些没有成功传达的事情:(i)&lt;dl&gt; 中有多个&lt;dt&gt;(ii)不能保证顺序,但如果它更容易,&lt;dt&gt;Foobar&lt;/dt&gt; 总是在&lt;dt&gt;Venus&lt;/dt&gt; 之前(两者之间有&lt;dd&gt;并不总是正确之前。
  • @NinoŠkopac 好吧,我只能处理您发布的内容。如果可能,请尝试使用实际的 html 或至少具有代表性的示例来编辑问题。
  • 我相信我有代表性样本 - 您认为哪一部分与我的描述不一致?另外,谢谢。
  • @NinoŠkopac 我无法真正回答这个问题。我所知道的是,给定问题中的示例 html,答案中的 xpath 表达式输出“MSG”和“Wembley”。由于您在实际 html 上得到一个空结果集,这意味着问题中的 html 不代表实际 html。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-01-27
  • 1970-01-01
  • 2011-01-31
  • 2011-04-05
  • 2019-09-15
  • 1970-01-01
相关资源
最近更新 更多