Python Selenium:如何在预期条件下应用“ And”逻辑运算符

问题描述

基本上,我想做的是在https://www.ssrn.com/index.cfm/en/搜索一个名称,然后单击一些部分匹配的名称。例如,我要搜索“ John Doe”。 SSRN将返回在其作者列表中包含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,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()的东西,但是我不确定如何实现它,或者是否有更好的方法来实现。谢谢!

解决方法

摘要

EC.presence_of_element_located((By.PARTIAL_LINK_TEXT,name.split(' ',1)[0])) and
EC.presence_of_element_located((By.PARTIAL_LINK_TEXT,1)[1]))

仅求和

EC.presence_of_element_located((By.PARTIAL_LINK_TEXT,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,1)[0]))(driver)
    second = EC.presence_of_element_located((By.PARTIAL_LINK_TEXT,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__call__函数的__init__来执行相同的操作-这称为对象函数,如果需要,也可以使用此函数-

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 did not meet
        return results[0] if len(set(results)) == 1 else False

您将使用与关闭模式完全相同的方式。

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...