I have below Selenium Python code to find the element in the aspx web page in dialog box.
for loop runs twice, during the first run its not finding the radio button. during second iteration its finds the radio button. In the loop I am just switching to frame 0.
I like to understand, why it’s not finding the element in first try? how it was able to find the element in second run?
**Sample code with drive option **
web_url = config['ARCHER_URL']
options = Options()
options.page_load_strategy = 'normal'
s = Service(web_driver)
driver = webdriver.Chrome(service=s, options=options)
driver.get(web_url)
logger.info(f"Loading the site {web_url}")
driver.implicitly_wait(10)
time.sleep(5)
driver.switch_to.frame(0)
frames = [0, 1]
for frame in frames:
logger.info(f"Switching to frame {frame}")
driver.switch_to.frame(0)
try:
element = driver.find_element(By.ID, "ExcludeButton")
if element:
logger.success("Found Radio button")
element.click()
break
except NoSuchElementException as e:
logger.warning("element not in this frame: " repr(e))
log message during the run
- Switching to frame 0
- element not in this frame: NoSuchElementException('no such element: Unable to locate el
- Switching to frame 1
- Found Radio button
CodePudding user response:
A probably better way would be using Waits:
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
...
wait = WebDriverWait(driver, 20)
...
wait.until(EC.frame_to_be_available_and_switch_to_it((By.XPATH, '//iframe[@name="great_iframe_name"]')))
wait.until(EC.element_to_be_clickable((By.ID, 'ExcludeButton'))).click()
Relevant documentation for Waits: https://www.selenium.dev/documentation/webdriver/waits/#explicit-wait
CodePudding user response:
Looks like the page is loading or changing after some action when you trying to find that element while you did not define driver.implicitly_wait
so it is set to it default value of 0 that means if driver.find_element
doesn't find the element instantly it throws exception.
To avoid such situations the best practice is to use WebDriverWait
expected_conditions
explicit waits. With them you can use for element presence, visibility, clickability and more.
So, your code can be improved as following:
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
wait = WebDriverWait(driver, 20)
try:
logger.info(f"Switching to frame {frame}")
driver.switch_to.frame(0)
wait.until(EC.element_to_be_clickable((By.ID, 'ExcludeButton'))).click()
logger.success("Found Radio button")
break
except NoSuchElementException as e:
logger.warning("element not in this frame: " repr(e))
The code above should work for the first attempt and not go to except
block ever.