如何使用 Capybara 找到紧跟在另一个元素之后的特定元素?

How can I find a certain element that comes right after another element with Capybara?

我正在尝试使用 learn Capybara 来完成我的抓取任务。到目前为止,我只将它用于测试。我想学习一百万件事,但在最基本的部分,我想知道如何找到某个元素,该元素是兄弟元素,并且在 另一个元素之后出现,我是能找到吗?

像这样拍一页:

<body>
  <h3>Name1</h3>
  <table>
    ...
  </table>
  <h3>Name2</h3>
  <table>
    ...
  </table>
  <h3>Name3</h3>
  <table>
    ...
  </table>
</body>

我想 return <h3> 元素之后的 <table> 元素具有文本 Name2.

我知道如何使用 all 遍历元素,我知道如何使用 first 而不是 find,但我不知道如何 "Find the first element X following specific element Y" ].

CSS

在 CSS 中,您可以使用同级 selector。这些允许您 select 兄弟元素;或那些处于相同嵌套级别且具有相同父元素的。有两种兄弟姐妹 select 或:

  • '+' 相邻兄弟select或
  • '~'一般兄弟姐妹select或(相邻或不相邻的兄弟姐妹)

通常最好尽可能避免通过文本进行匹配。 (这使您的规格更容易编写,也意味着文本更改不太可能破坏您的规格。)在那个理想的世界中,您的 'h3' 元素可能具有 ID,我们可以:

find('h3#name2+table')

但是,在您的示例中,它们没有 ID,因此让我们将几个查询连接到我们想要的范围。

find('h3', text: 'Name2').find('+table')

首先,我们找到了正确的 'h3' 元素(使用文本匹配),然后以该查询为基础,我们请求同级 'table' 元素。

您可能还会注意到,如果您使用通用同级 select 或“~”,您会得到一个不明确的元素错误;水豚找到了所有 'table' 个元素,而不仅仅是相邻的一个。

XPath

有时,如果您真的被迫处理文本元素,XPath 实际上更容易使用 selection。所以你可以改为:

find(:xpath, "//h3[contains(text(),'Name2')]/following-sibling::table")

更难读,但做同样的事情。首先找到带有文本 'Name2' 的 'h3',然后 select 它是兄弟 'table' 元素。

Capybara 现在有 siblingancestor 个查找器 (~>=2.15.0)

[2018/09 更新] 正如@trueunlessfalse 注释掉的那样,如果有多个匹配项,使用 sibling 查找器的原始答案将 return amgibuous match error 。所以,请考虑在这种情况下使用 xpath..

以下使用 xpath 的代码将 return OP 想要的

find('h3', text: 'Name2').first(:xpath, './following-sibling::table')


以下代码将return OP 想要的 => 歧义匹配错误

find('h3', text: 'Name2').sibling('table')

您可以在此处查看详细信息。 https://www.rubydoc.info/github/jnicklas/capybara/Capybara/Node/Finders:sibling

正在使用

find('h3#name2+table')

对我没用。我需要添加 :css 然后它工作

find(:css, 'h3#name2+table')