Selenium Python 通过 2 个可能的 ID 搜索元素
Selenium Python Searching Element By 2 possible ID
我想使用 ID 查找元素,但网络似乎有时会更改 ID。
有2个ID,第一个ID可以让我直接输入邮箱,但是如果出现第二个ID,我需要先点击一个按钮,然后再输入我的邮箱。我试过使用 if
和 else
逻辑,但它显示了一些错误。
这是我的代码:
@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/
我想使用 ID 查找元素,但网络似乎有时会更改 ID。
有2个ID,第一个ID可以让我直接输入邮箱,但是如果出现第二个ID,我需要先点击一个按钮,然后再输入我的邮箱。我试过使用 if
和 else
逻辑,但它显示了一些错误。
这是我的代码:
@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/