我正在尝试使用学习 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 。
答案 0 :(得分:8)
在CSS中你可以使用兄弟选择器。这些允许您选择兄弟元素;或者那些处于相同嵌套级别且具有相同父元素的那些。有两种类型的兄弟选择器:
通常尽可能避免文本匹配。 (这使您的规范更容易编写,也意味着文本更改不太可能破坏您的规范。)在理想世界中,您的'h3'元素可能有ID,我们可以只是:
find('h3#name2+table')
但是,在您的示例中,他们没有ID,所以让我们将几个查询连接到我们想要的范围。
find('h3', text: 'Name2').find('+table')
首先我们找到了正确的'h3'元素(使用文本匹配),然后以该查询作为基础,我们请求兄弟'table'元素。
您可能还会注意到,如果您使用了通用兄弟选择器'〜',则会出现模糊元素错误; Capybara找到了所有“桌子”元素,而不仅仅是相邻元素。
如果您真的被迫进行文本元素选择,有时XPath实际上更容易使用。所以你可以改为:
find(:xpath, "//h3[contains(text(),'Name2')]/following-sibling::table")
更难读,但做同样的事情。首先找到带有'Name2'文本的'h3',然后选择它的兄弟'table'元素。
答案 1 :(得分:3)
sibling
和ancestor
查找者(〜> = 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')