Selenium Python 通过 2 个可能的 ID 搜索元素

Selenium Python Searching Element By 2 possible ID

我想使用 ID 查找元素,但网络似乎有时会更改 ID。

有2个ID,第一个ID可以让我直接输入邮箱,但是如果出现第二个ID,我需要先点击一个按钮,然后再输入我的邮箱。我试过使用 ifelse 逻辑,但它显示了一些错误。 这是我的代码:

@pytest.mark.parametrize('a,b', key0)
def test_login_successful(self, a,b):
    time.sleep(5)
    if WebDriverWait(driver, 10).until(EC.visibility_of_element_located((By.ID, 'login-find-account-form'))) == True:
        pass

    else:
    # WebDriverWait(driver, 10).until(EC.visibility_of_element_located((By.ID, 'login-form')))
        WebDriverWait(driver, 20).until(EC.element_to_be_clickable(
            (By.XPATH, '//*[@id="login-form"]/div[1]/div/div/div/a'))).click()

    email_box = '//*[@id="user_name"]'
    email_input = driver.find_element_by_xpath(email_box)
    email_input.send_keys(a)

    submit = driver.find_element_by_xpath('//*[@id="submit_button"]').click()
    

如果您有任何想法,我将不胜感激。

谢谢

您可以改用 CSS 选择器,如下所示:

ID_1 = WebDriverWait(driver, 10).until(EC.visibility_of_element_located((By.CSS, '#login-form,#login-find-account-form')))

逗号用作 CSS 的 OR 运算符,如果找不到第一个,则会尝试找到第二个。重要的是您要知道此选择器不能用作 AND,这意味着它不会 return 两个结果。

编辑:

有一种简单的方法可以实现这一点(不是正确的方法)。

轻松实现您的需求:

@pytest.mark.parametrize('a,b', key0)
def test_login_successful(self, a,b):
    time.sleep(5)

    # The element to be found on the second condition
    element_of_interest = driver.find_elements_by_xpath('//*[@id="login-form"]/div[1]/div/div/div/a')

    # element_of_interest is a list, if is empty this condition
    # is not valid and then it won't attempt to click on it
    if element_of_interest:
        element_of_interest[0].click()

    email_box = '//*[@id="user_name"]'
    email_input = driver.find_element_by_xpath(email_box)
    email_input.send_keys(a)

    submit = driver.find_element_by_xpath('//*[@id="submit_button"]').click()

这里有几点意见。看起来你并不真的需要第一个条件,因为你没有在那里做任何事情。因此我只添加了第二个条件。

如果您查看解决方案,您会发现使用的是 find_elements_by_xpath(复数形式)而不是 find_element_by_xpath,原因是如果找不到该元素,则 find_elments_by_xpath 将 return 一个空列表。

如果您需要等待 10 秒直到这些元素之一出现,那么您可以这样做:

@pytest.mark.parametrize('a,b', key0)
def test_login_successful(self, a,b):
    time.sleep(5)

    # The element to be found on the second condition
    element1 = driver.find_elements_by_id('login-find-account-form')
    element2 = driver.find_elements_by_xpath('//*[@id="login-form"]/div[1]/div/div/div/a')

    # Waits up to 10 seconds to find either element 1 or 2
    retries = 10
    while not element1 or not element2:
         time.sleep(1)
         retries -= 1
         if retries < 0:
            raise Exception("some exception in here")
         element1 = driver.find_elements_by_id('login-find-account-form')
         element2 = driver.find_elements_by_xpath('//*[@id="login-form"]/div[1]/div/div/div/a')
       
    # element2 is a list, if is empty this condition
    # is not valid and then it won't attempt to click on it
    if element2:
        element2[0].click()

    email_box = '//*[@id="user_name"]'
    email_input = driver.find_element_by_xpath(email_box)
    email_input.send_keys(a)

    submit = driver.find_element_by_xpath('//*[@id="submit_button"]').click()

对此有更好的实现我建议查看 selenium 的页面对象模型文档,您可以从该设计模式中获益良多:https://www.selenium.dev/documentation/guidelines/page_object_models/