0

基本上,我想做的是在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, 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() 的东西,但我不确定如何实现它,或者是否有更好的方法来做到这一点。谢谢!

4

1 回答 1

1

片段

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)]))

请注意,我正在使用闭包模式来执行此操作。在内部,使用seleniumaclass和函数来做同样的事情 - 这被称为对象之类的函数,如果你愿意,你也可以使用它 -__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

您可以使用与闭包模式完全相同的方式。

于 2020-10-27T15:02:26.133 回答