如何使用带有 Python 或 Perl 的 Selenium 查找活动元素的相邻元素

How to find the neighbour element of an active element using Selenium with Python or Perl

这是

的逆题
$driver.get_element_by_xpath(....)

背景

我有一系列动态生成的页面需要解析。目标元素没有合适的定位器、xpath、文本或 ID。然而,邻居元素有一个唯一的文本来匹配。我的计划是定位相邻元素并使用其 xpath 得出目标 xpath。

$neighbor_element = $driver.get_element_by_text("unique text"); # or some other way
$neighbor_xpath = $neighbor_element.xpath; # this step is the question
$target_xpath = modify($neighbor_xpath); # this is my function
$target_element = $driver.get_element_by_xpath($target_xpath);

我到处找了找。找不到从元素、Perl 或 Python.

获取 xpath 的函数或方法

更新

很抱歉我无法 post 示例页面,因为它归一家公司所有,但我希望问题足够直截了当。 当我使用 chrome devtools 检查时,我看到 xpath 是相关的

neighbor xpath = //*[@id="lable_ni.dynmic_string 123456"]/lable/span[2]
target   xpath = //*[@id="dynmic_string 123456"]

更新2

这是虚拟测试文件

<!DOCTYPE html>
<html>

<head></head>

<body>
    <div>
        <div id="lable_ni.dynmic_string 123456">
            <label id="lable_ni.dynmic_string 123456">
                <!-- I use this as neighbour element -->
                <span>unique text</span>
            </label>
        </div>
        <div>
            <!-- target element is here -->
            <textarea id="dynmic_string 123456">target text is here</textarea>
        </div>
    </div>
</body>

</html>

这是它的样子

我的策略是

  1. 找到“唯一文本”的xpath。 (此文本是事先已知的)
  2. 转换为目标文本的xpath
  3. 获取目标文本

我卡在了第一步

使用 Selenium Python 客户端 以防您能够将相邻元素定位为:

neighbor_element = driver.find_element(By.XPATH, "unique text")

根据目标元素相对于 neighbor_element 的位置,您可以使用以下任一项 :

  • Incase target_element 是一个 <span> 元素位于 neighbor_element:

    target_element = driver.find_element(locate_with(By.TAG_NAME, "span").to_left_of(neighbor_element))
    

您必须包括以下导入:

from selenium.webdriver.support.relative_locator import locate_with

找到那个“known-neighbor”的 parent 然后他们的 select child, 或 children 在已知列表中的下一个一.

我对目标的已知信息有些困惑。原文是这样说的

The target element doesn't have a good locator, xpath, text, or id.

但编辑显示

target xpath = //*[@id="dynmic_string 123456"]

因为必须有 一些 方式来告诉我,我会把它当作一个事实,即关于目标的一些事情是已知的。另一种方法是获取所有 children(因此,所有兄弟姐妹)并浏览它们并找到已知的兄弟姐妹。

这是一个 Perl 示例。对于这个页面,将 known-neighbor 视为带有一些文本的 <p> 并找到作为兄弟 <p> 并且其中包含一些给定文本的目标。 (相当于找到问题编辑中给出的 id 的兄弟姐妹。)

use warnings;
use strict;
use feature 'say';

use Selenium::Chrome;

my $url_SO = q(
    . q(how-to-find-the-neighbour-element-of-an-active-element-)
    . q(using-selenium-with-pytho);

my $drv = Selenium::Chrome->new( 'extra_capabilities' => 
    { 'goog:chromeOptions' => { args => [ 'headless' ] }}  );

$drv->get($url_SO);
say "\nPage title: ", $drv->get_title, "\n";

# Our "neighbor": <p> with text 'This is...'
# Get parent with: 'element-spec/..'
my $parent = eval { 
    $drv->find_element(
        '//p[text()="This is a inverse question of"]/..') };
if ($@) { die "Error on <p>'s parent: $@" }
say "known-<p>'s parent tag: ", $parent->get_tag_name;
say "known-<p>'s parent text:";
say '-'x50, "\n", $parent->get_text, "\n", '-'x50;

# Target: <p> with text that contains word 'searched'
my $tgt = eval { 
    $drv->find_child_element( 
        $parent, q(./p[contains(text(), 'searched')]) ) };    
if ($@) { die "find-child error: $@" }
say "target text: ", $tgt->get_text;

这符合预期。我真的无法 post 更接近问题,因为给出的不多。如果我误解了显示的 id 目标是已知的,那么在 $parent 上使用 find_child_elements 并向下搜索已知邻居的列表。目标应该是之前或之后的那个(你最好知道是哪个:)

如果目标实际上不是真正的兄弟姐妹,而是更进一步上升的 child(而不是直接的 parent),则 xpath 表达式可以上升到层次结构额外的 /../.. (等等)。

这使用了 (server-less) Selenium::Chrome, with methods in Selenium::Remote::Driver and Selenium::Remote::WebElement

(应该可以用一个 XPath 表达式完成整个 known-element->parent->child 的事情,或者甚至直接寻找兄弟姐妹,我'有空再看看。)