Python Selenium:如何在预期条件下应用 "And" 逻辑运算符
Python Selenium: How to apply "And" logical operator in expected condition
基本上,我想做的是搜索 https://www.ssrn.com/index.cfm/en/ 一个名字,然后点击一些部分匹配的名字。例如,我想搜索“John Doe”。 SSRN 将 return 作者列表中包含 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)。然后,我的代码会select李四。我想我想要类似于 Java 的 EC.and() 的东西,但我不确定如何实现它或者是否有更好的方法来实现它。谢谢!
片段
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
因为它之前出现过。
这不是检查多个条件的方式,您需要将一个 function-like 对象传递给 .until
,它可以检查多个条件和 return 一个 truthy/falsy值。
根据您的特定需求,该功能可能类似于-
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
这将尝试查找具有部分 link 文本“John”的元素,然后它将尝试查找具有部分 link 文本“Doe”的元素 - 如果找到这两个元素并且如果两者都指向同一个元素 - 你就是黄金。
你可以像这样在你的 until 中使用它-
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
使用带有 __init__
和 __call__
函数的 class
来做同样的事情——这被称为类似对象的函数,如果你愿意,你也可以使用它——
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
您将以与闭包模式完全相同的方式使用它。
基本上,我想做的是搜索 https://www.ssrn.com/index.cfm/en/ 一个名字,然后点击一些部分匹配的名字。例如,我想搜索“John Doe”。 SSRN 将 return 作者列表中包含 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)。然后,我的代码会select李四。我想我想要类似于 Java 的 EC.and() 的东西,但我不确定如何实现它或者是否有更好的方法来实现它。谢谢!
片段
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
因为它之前出现过。
这不是检查多个条件的方式,您需要将一个 function-like 对象传递给 .until
,它可以检查多个条件和 return 一个 truthy/falsy值。
根据您的特定需求,该功能可能类似于-
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
这将尝试查找具有部分 link 文本“John”的元素,然后它将尝试查找具有部分 link 文本“Doe”的元素 - 如果找到这两个元素并且如果两者都指向同一个元素 - 你就是黄金。
你可以像这样在你的 until 中使用它-
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
使用带有 __init__
和 __call__
函数的 class
来做同样的事情——这被称为类似对象的函数,如果你愿意,你也可以使用它——
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
您将以与闭包模式完全相同的方式使用它。