我正在努力让Selenium经历大量替代条件XPath,寻找可能匹配的元素 - 并将其传递给对象elmnt
。
目前,使用OR
运算符(|
),代码很快就会变得非常重复和详尽,尤其是在存在大量可能的变体时。
在下面的示例中,唯一的变化是我开始寻找h1
,h2
或h3
。其余的都一样。
for word in ["testString1", "testString2", "testString3"]:
try:
elmnt = driver.find_element_by_xpath(
(
"//h1[text()[contains(., '%s')]]" % word +
"/following::p" +
"|" +
"//h1[text()[contains(., '%s')]]" % word +
"/following::span" +
"|" +
"//h2[text()[contains(., '%s')]]" % word +
"/following::p" +
"|" +
"//h2[text()[contains(., '%s')]]" % word +
"/following::span" +
"|" +
"//h3[text()[contains(., '%s')]]" % word +
"/following::p" +
"|" +
"//h3[text()[contains(., '%s')]]" % word +
"/following::span"
)
).text
except:
pass
else:
print elmnt
break
但在我的实际代码中,除了/following::
和p
之外,我还会考虑更多变体,包括span
中的各种节点类型。
问题:有没有办法简化(缩短)这个?
我的第一个希望是可以做类似的事情:
"//[h1|h2|h3][text()[contains(., '%s')]]" % word
即。 or
运算符可以“烘焙到”XPath表达式,而不必像示例中那样使用完全详尽的字符串连接。如果是这样,那个想法可以全面应用。
然而,这似乎不可能。
解决方案是创建某种生成函数来创建整个xPath字符串,还是别的什么?
答案 0 :(得分:2)
我会使用这个缩短的XPath(根据@alecxe in a comment的建议利用self::
轴):
"//*[self::h1 or self::h2 or self::h3][contains(., '%s')]" % word
+ "/following::*[self::p or self::span]"
请注意,这会测试h1
,h2
或h3
的字符串值是否包含word
变量的值(而不是直接文本节点的字符串值)。另外,如果您想要实际测试这些元素的字符串值是而不是包含 word
,请改用[.='%s']
。