Python Selenium - 根据跨度的内部文本获取同级链接

问题描述 投票:0回答:1

我已经为此工作了几个小时,但似乎无法将所有部分放在一起...... 所以给出:

<a href="link1">link</a>
<span class="class_name">00A<span>
...
<a href="link2">link</a>
<span class="class_name">00B<span>
...
<a href="link3">link</a>
<span class="class_name">01B<span>
...
<a href="link4">link</a>
<span class="class_name">01A<span>

我试图根据 span 的内部文本获取链接。所以我知道... 我可以获得所有链接:

links = [my_elem.get_attribute("href") for my_elem in WebDriverWait(driver, 30).until(EC.visibility_of_all_elements_located((By.XPATH, "//span[contains(@class, 'class_name')]//preceding-sibling::a[@href]")))]

我可以通过以下方式获取单个跨度上的文本:

print(driver.find_element(By.XPATH, "//span[contains(@class, 'class_name')]").text)

但我无法使用 find 元素来获取所有文本进行测试,因为它要求列表的文本。 我应该能够使用:

[contains(text(), '\\d+[A]')]")

但我不知道如何将它与所有链接的代码结合起来。我觉得我忽略了一些非常愚蠢的事情,但现在是早上 6:30,我昨天晚上开始做这个项目,所以我放弃了,只是去问更聪明的人。预先感谢您的帮助。

python selenium-webdriver xpath
1个回答
0
投票

注意

contains()
函数的第二个参数不是正则表达式;它是一个纯字符串,需要在第一个字符串参数中查找。我相信使用 Selenium 你会被 XPath 1.0 困住,它没有任何正则表达式函数。

在不使用正则表达式的情况下,如果您想过滤一组

span
元素以仅包含文本内容由一串数字后跟单个
A
组成的元素,则需要使用更复杂的表达式,其中组合了一堆字符串函数,例如像这样的东西:

span[
   contains(., 'A') and
   contains('0123456789', substring(., 1, 1)) and 
   translate(substring-before(., 'A'), '0123456789', '') = '' and
   substring-after(., 'A') = ''
]

注意,

.
是对“上下文节点”的引用,在谓词表达式中表示
span
元素之一。

这个表达的意思是:

span
元素

  • 其中某处包含
    A
    字符;和
  • 第一个字符是数字;和
  • A
    之前的文本完全由数字组成;和
  • A
    之后没有任何文字(即最后只有一个
    A

顺便说一句,我不确定这个表达式是否符合您的想法:

//span[contains(@class, 'class_name')]//preceding-sibling::a[@href]

澄清一下:XPath 中的

//
是表达式 /descendant-or-self::node()/
缩写
。所以你的表达式可以写成:

//span[contains(@class, 'class_name')]
   /descendant-or-self::node()/preceding-sibling::a[@href]

这将返回每个

a
元素(具有
href
属性),后面跟着一个兄弟元素,即 either:

  • 一个
    span
    元素,其
    class
    属性为
    'class_name'
  • span
    元素的后代,其
    class
    属性为
    'class_name'

如果您知道

span
a
实际上是兄弟姐妹,那么您可以将
//
替换为更简单的
/
(在我下面的建议中)。

这里要注意的另一件事是,除非每对

span
(或
span
后代)和
a
都包含在父元素中,否则
preceding-sibling::a[@href]
步骤将返回a
元素在
span
之前,而不仅仅是第一个这样的
span
(我怀疑你想要做什么,因为我认为是在
span之前的立即
为链接提供了标签。你可以将谓词 
[1]
 应用于 
a[@href]
 元素集以仅获取第一个(按 
preceding-sibling
 顺序)。

因此,为了结合这些想法,这是我的建议:

//span [contains(@class, 'class_name')] [ contains(., 'A') and contains('0123456789', substring(., 1, 1)) and translate(substring-before(., 'A'), '0123456789', '') = '' and substring-after(., 'A') = '' ] //preceding-sibling::a[@href][1]
应用于此输入:

<body> <a href="link1">link</a> <span class="class_name">00A</span> ... <a href="link2">link</a> <span class="class_name">00B</span> ... <a href="link3">link</a> <span class="class_name">01B</span> ... <a href="link4">link</a> <span class="class_name">01A</span> </body>
...它产生:

<a href="link1">link</a> <a href="link4">link</a>
    
© www.soinside.com 2019 - 2024. All rights reserved.