如何使用 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 现在有 sibling
和 ancestor
个查找器 (~>=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')
我正在尝试使用 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 现在有 sibling
和 ancestor
个查找器 (~>=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')