-1

I almost sure that there are few simple solutions for that, but.. i'm clicking an element of web page and one of more than 2 different pages can appear after it. Than i need to click one of the specific elements for each kind of result pages.
If i had 2 variants i could use TRY and EXCEPT + WebDriverWait.until structures.

lesson = driver.find_element_by_xpath('//input[@class = "playButton"]')
lesson.click()
try:
    WebDriverWait(driver, 3).until(EC.element_to_be_clickable((By.XPATH, '//div[@class = "cursor-hover"]')))
    start_b = driver.find_element_by_xpath('//div[@class = "cursor-hover"]')
    start_b.click()
except:
    WebDriverWait(driver, 2).until(EC.element_to_be_clickable((By.XPATH, '//div[@class = "cursor-hover2"]')))
    start_g = driver.find_element_by_xpath('//div[@class = "cursor-hover2"]')
    start_g.click()

This structure works perfect. If there is no first element - the second one is clicked. So what can i use to successfully identify the only element of 5 or more?

4 Answers4

1

Probably having a list of possible xpaths and iterating through them would be the easiest solution.

# possible xpaths depending on what page will be opened afterwards
possible_xpaths = ['//div[@class = "cursor-hover1"]', '//*[@class="something else"]', ...]

for xpath in possible_xpaths:
    try:
        WebDriverWait(driver, 3).until(EC.element_to_be_clickable((By.XPATH, xpath)))
        element = driver.find_element_by_xpath(xpath)
        element.click()
        break # found the correct element
    except:
        pass # continue to try the next xpath
questioning
  • 245
  • 1
  • 4
  • 18
0

Thank you all! The best solution is to use a loop and list of xpaths. Looks accurate and works well

start_path = [
'//div[@class = "item image vectorshape item_5VQC0609M6a textlib"]',
'//div[@aria-label = "GetStarted01.png"]',
'//div[@data-model-id = "6qik7pRD2IF_ResumePromptSlide_btn0"]',
'//div[@id = "6XuNknTrhpP.6ZEBMbiB1Jo.655Ij3xXJBL.5cP2lAl8Izg.67Nc1dZxOLf"]/canvas',
'//div[@class = "slide-object slide-object-button shown cursor-hover      "]',
'//div[@class = "item image vectorshape item_6REUhB7StMI textlib"]'

def buttonfinder(path_list):
time.sleep(5)
for path in path_list:
    try:
        print(path)
        WebDriverWait(driver, 1).until(EC.element_to_be_clickable((By.XPATH, path))).click()
        break
    except:
        pass
0

The way:

import time
from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from webdriver_manager.chrome import ChromeDriverManager
from selenium.webdriver.common.by import By
from selenium.common.exceptions import NoSuchElementException

s=Service(ChromeDriverManager().install())
options = webdriver.ChromeOptions() 
options.add_experimental_option("excludeSwitches", ["enable-automation"])
options.add_experimental_option('useAutomationExtension', False)
driver = webdriver.Chrome(service=s, options=options)

def trye():
    driver.get('https://google.com')

    for trytimes in range(15):
        try:
            a = driver.find_element(By.XPATH, '/html/body/div[1]/div[2]/div/img').is_displayed()
            b = driver.find_element(By.XPATH, '/html/body/div[1]/div[3]/form/div[1]/div[1]/div[1]/div/div[2]/input').is_displayed()
            if a and b:
                return True
        except NoSuchElementException:
            time.sleep(1)
            continue
        except:
            return False
    else:
        return False

print(trye())
boludoz
  • 36
  • 4
-1

If i understand correctly you need to tweak your xpath a little like this could solve your problem, make sure xpath is unique for page.

lesson = driver.find_element_by_xpath('//input[@class = "playButton"]')
lesson.click()

WebDriverWait(driver, 3).until(EC.element_to_be_clickable((By.XPATH, '//div[@class = "cursor-hover"]|//div[@class = "cursor-hover2"]')))

start_b = driver.find_element_by_xpath('//div[@class = "cursor-hover"]|//div[@class = "cursor-hover2"]')
start_b.click()

Or to make it more simple you can also just click with wait.

WebDriverWait(driver, 3).until(EC.element_to_be_clickable((By.XPATH, '//div[@class = "cursor-hover"]|//div[@class = "cursor-hover2"]'))).click()

if using xpath with pipe delimiter doesn't suite and you want to stick to exception then i would recommend you to identify the page first then add wait otherwise adding webdriverwait for 5 pages will take too long to get to fifth page so instead

try something link

if driver.find_element_by_xpath('//some title or specific element of page'):
    WebDriverWait(driver, 3).until(EC.element_to_be_clickable((By.XPATH, 'xpath for that page'))).click()
Assad Ali
  • 288
  • 1
  • 12
  • Incomprehensible description, right. Ok, I need to check if one of several (3 or more) known elements is present on the open page and click on it – mr. Wayfarer Oct 03 '21 at 15:46
  • well you can use more than one xpaths with pipe delimiter so you don't need to use multiple webdriverwaits in case there are multiple pages, and adding condition would reduce time to wait for each page, that is the would summery of it – Assad Ali Oct 03 '21 at 15:55