Python Selenium:如何在预期条件下应用“与”逻辑运算符
Posted
技术标签:
【中文标题】Python Selenium:如何在预期条件下应用“与”逻辑运算符【英文标题】:Python Selenium: How to apply "And" logical operator in expected condition 【发布时间】:2021-02-09 18:49:56 【问题描述】:基本上,我想做的是搜索https://www.s-s-rn.com/index.cfm/en/ 的名称,然后单击一些部分匹配的名称。例如,我想搜索“John Doe”。 s-s-rN 将返回在其作者列表中包含 John Doe 的论文列表。下面是我尝试这样做的代码。
name = "John Doe"
try:
element = WebDriverWait(driver, 10).until(
EC.presence_of_element_located((By.PARTIAL_LINK_TEXT, name.split(' ', 1)[0])) and
EC.presence_of_element_located((By.PARTIAL_LINK_TEXT, name.split(' ', 1)[1]))
)
# I want the element to be clicked only if both the first name and last name appear.
element.click()
except:
print("No result")
如果 John Doe 完全匹配,即作者列表看起来像 (John Doe, x, y, z),则此方法有效。如果 John Doe 是部分匹配并且没有其他部分匹配,则它有效,即作者列表看起来像 (John M. Doe, x, y, z)。但是,如果有多个部分匹配,它会中断。例如,如果列表看起来像 (Jane Doe, John Doe, y, z)。然后,我的代码将选择 Jane Doe。我想我想要类似于 Java 的 EC.and() 的东西,但我不确定如何实现它,或者是否有更好的方法来做到这一点。谢谢!
【问题讨论】:
.until
应该返回哪个元素?因为您实际上是在尝试找到 2 个元素
我希望元素与“John”和“Doe”都匹配。因此,如果有意义的话,可能是 John M. Doe 或 John Jack Doe 或 John Doe。
【参考方案1】:
sn-p
EC.presence_of_element_located((By.PARTIAL_LINK_TEXT, name.split(' ', 1)[0])) and
EC.presence_of_element_located((By.PARTIAL_LINK_TEXT, name.split(' ', 1)[1]))
只计算为
EC.presence_of_element_located((By.PARTIAL_LINK_TEXT, name.split(' ', 1)[1]))
所以它总是只检查那个条件和那个条件,即它总是只试图找到Doe
,完全忽略John
。这就是为什么您会找到 Jane Doe
,因为它之前出现过。
这不是您检查多个条件的方式,您需要将一个类似函数的对象传递给.until
,它可以检查多个条件并返回一个真假值。
对于您的特定需求,该功能可能看起来像-
def presence_of_element_with_both(driver):
name = "John Doe"
first = EC.presence_of_element_located((By.PARTIAL_LINK_TEXT, name.split(' ', 1)[0]))(driver)
second = EC.presence_of_element_located((By.PARTIAL_LINK_TEXT, name.split(' ', 1)[1]))(driver)
if first == second:
# Both elements exist and they are the same
return first
else:
return False
这将尝试查找带有部分链接文本“John”的元素,然后它将尝试查找带有部分链接文本“Doe”的元素 - 如果两个元素都找到并且都指向同一个元素 - 你'重金。
你可以在你的直到像这样使用它-
WebDriverWait(driver, 10).until(presence_of_element_with_both)
但是,您可能会发现将其概括起来很方便-
def presence_of_element_with_all(locators):
def inner(driver):
# Get all the elements that match each given locator
results = [EC.presence_of_element_located(locator)(driver) for locator in locators]
# Check if all the elements are the same
# If they are, all the conditions have been met
# If they are not, all the conditions did not meet
return results[0] if len(set(results)) == 1 else False
return inner
这将找到满足所有给定定位器的奇异元素。
你可以这样使用-
first_name, last_name = "John Doe".split(' ')
WebDriverWait(driver, 10).until(presence_of_element_with_all([(By.PARTIAL_LINK_TEXT, first_name), (By.PARTIAL_LINK_TEXT, last_name)]))
请注意,我正在使用闭包模式来执行此操作。在内部,selenium
使用 class
和 __init__
和 __call__
函数来做同样的事情 - 这被称为类似对象的函数,如果你愿意,你也可以使用它-
class presence_of_element_with_all:
def __init__(self, locators):
self.locators = locators
def __call__(self, driver):
results = [EC.presence_of_element_located(locator)(driver) for locator in self.locators]
# Check if all the elements are the same
# If they are, all the conditions have been met
# If they are not, all the conditions did not meet
return results[0] if len(set(results)) == 1 else False
您可以使用与闭包模式完全相同的方式。
【讨论】:
非常感谢您提供如此详尽的回答!它确实有效。我也一直在尝试涉足一些更复杂的东西,您的回答也对此有所帮助。以上是关于Python Selenium:如何在预期条件下应用“与”逻辑运算符的主要内容,如果未能解决你的问题,请参考以下文章
当 Selenium 中的预期条件失败时,不遵守 waitTime
selenium.common.exceptions.InvalidArgumentException:消息:无效参数:“使用”必须是使用等待和预期条件的字符串