我怎样才能找到一个跟随Capybara的另一个元素之后的元素?

时间:2015-05-13 05:09:40

标签: html css xpath css-selectors capybara

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

采取这样的页面:

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

我想返回<table>元素之后的<h3>元素,该元素包含文本 Name2

我知道如何使用all循环播放元素,并知道如何使用first代替find,但我不知道如何使用using System; using System.Diagnostics; using System.Linq; using System.Collections.Generic; using System.Text; namespace ConsoleApplication1 { class Program { static void Main(string[] args) { Console.WriteLine("Time per run was: " + SimpleTest()); } const int Runs = 10; const int Width = 5000; const int Height = 5000; const int Size = Width * Height; static int[] Input = Enumerable.Range(0, Size).ToArray(); static int[] Output = new int[Size * 2]; static float SimpleTest() { // Removing those 2 lines and using the static arrays instead give substantially slower performance, nearly half the speed! //int[] Input = Enumerable.Range(0, Size).ToArray(); //int[] Output = new int[Size * 2]; Stopwatch sw = new Stopwatch(); sw.Start(); for (int run = 0; run < Runs; run++) { int InputIndex = 0; for (int x = 0; x < Width; x++) { for (int y = 0; y < Height; y++) { int pixel = Input[InputIndex]; var OutputIndex = InputIndex * 2; Output[OutputIndex] = pixel; Output[OutputIndex + 1] = pixel; InputIndex++; } } } sw.Stop(); return (sw.ElapsedMilliseconds / (float)Runs); } } } 在特定元素 Y &#34;之后找到第一个元素 X

3 个答案:

答案 0 :(得分:8)

CSS

在CSS中你可以使用兄弟选择器。这些允许您选择兄弟元素;或者那些处于相同嵌套级别且具有相同父元素的那些。有两种类型的兄弟选择器:

  • '+'相邻的兄弟选择器
  • '〜'一般兄弟选择器(相邻或不相邻的兄弟姐妹)

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

find('h3#name2+table')

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

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

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

您可能还会注意到,如果您使用了通用兄弟选择器'〜',则会出现模糊元素错误; Capybara找到了所有“桌子”元素,而不仅仅是相邻元素。

的XPath

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

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

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

答案 1 :(得分:3)

水豚现在拥有siblingancestor查找者(〜> = 2.15.0)

[2018/09更新] 正如@trueunlessfalse注释掉一样,如果存在多个匹配项,则使用sibling查找程序的原始答案将返回amgibuous match error。因此,在这种情况下,请考虑使用xpath。

使用xpath的以下代码将返回OP想要的内容

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


以下代码将返回OP想要的内容 =>模糊匹配错误

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

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

答案 2 :(得分:0)

使用

find('h3#name2+table')

为我工作。我需要添加:css才能成功

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