问题描述
基本上,我想做的是在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
您将使用与关闭模式完全相同的方式。