Selenium cannot find element in main window
Question:
I am attempting to download a file from a website using Selenium and Python 3. This requires pressing a confirmation button on an overlay window. The overlay window is not within an iFrame – the HTML is simply dynamically added when the overlay appears – but Selenium is not able to find the button by xPath, returning a NoSuchElementException
. Am I missing anything that would cause Selenium not to be able to see the element as it appears in the page source? So far as I can tell, Selenium should be able to locate the button with no issue.
#Initialize Driver
driver = webdriver.Safari()
cmd = "osascript -e 'tell application "Safari" to set bounds of front window to {0, 22, 1500, 1022}'"
os.system(cmd)
#Call up seach link
driver.get(data_url)
wait_a = WebDriverWait(driver, 15)
element = wait_a.until(EC.presence_of_element_located((By.ID, "md-input-3")))
#Initialize and send login information (defined above)
username = driver.find_element_by_id("md-input-3")
password = driver.find_element_by_id("md-input-6")
username.send_keys(crunchbase_username)
password.send_keys(crunchbase_password)
#Click login button
password.send_keys(Keys.ENTER)
#Wait for results page to finish loading
wait = WebDriverWait(driver, 15)
element = wait.until(EC.title_contains("Signals"))
time.sleep(2)
#Press Download Button
driver.find_element_by_xpath("//button[@aria-label='Export your results']").click()
time.sleep(2)
#Press csv button
driver.find_element_by_xpath("//button[@aria-label='Export to CSV']").click()
time.sleep(2)
#Confirm downlaod
driver.find_element_by_xpath("//*[@id='cdk-overlay-36']/md-dialog-container/confirmation-dialog/dialog-layout/div/md-dialog-actions/div/button[2]").click()
#Close driver
#driver.close()
The page source is overly complicated and highly stylized so I will not include it here, but a screenshot of the relevant section of the code in my browser’s web inspector is below. The element which I’m trying to click is highlighted in blue.
I appreciate any help with this.
Answers:
Before clicking on the element, execute the following lines:
WebElement element = driver.findElement(By.xpath(" path_of_your_module "));
((JavaScriptExecutor) driver). executeScript("argument[0].scrollIntoView(true);", element);
It is hard to tell without having access to the page under question and being able to see what’s going. Few general points:
- Try css selectors instead of xpath. They are more robust, easier to work with and fast.
- Acvoid using dynamically generated IDs. In your screenshot I can’t even see an id that appears in your code.
- When you have more than one element of the same kind (like buttons in your case) try getting all webelements under a certain parent and test all of them for having an attribute value that you are looking for.
For example:
elemItems = driver.find_elements_by_css_selector(menuItemSelector)
for element in elements:
if element.text == "export":
elemItems[1].click()
Here, you find all the elements of a certain type (buttons for example) and select one that has “export” text in it.
I faced the same issue on a dialogOverlay and I fixed it. I realized that on clicking the overlay button that would bring the overlay, selenium was searching for the element before the overlay loads the dynamic content. So I did this:
def download():
global browser
notFound = True
while(notFound):
try:
elem = browser.find_element(By.ID, 'btnFormat2')
elem.click()
notFound = False
except BaseException:
print("----Error Download Element not found")
download()
The code will continuously look for the element until its loaded on the overlay.
I am attempting to download a file from a website using Selenium and Python 3. This requires pressing a confirmation button on an overlay window. The overlay window is not within an iFrame – the HTML is simply dynamically added when the overlay appears – but Selenium is not able to find the button by xPath, returning a NoSuchElementException
. Am I missing anything that would cause Selenium not to be able to see the element as it appears in the page source? So far as I can tell, Selenium should be able to locate the button with no issue.
#Initialize Driver
driver = webdriver.Safari()
cmd = "osascript -e 'tell application "Safari" to set bounds of front window to {0, 22, 1500, 1022}'"
os.system(cmd)
#Call up seach link
driver.get(data_url)
wait_a = WebDriverWait(driver, 15)
element = wait_a.until(EC.presence_of_element_located((By.ID, "md-input-3")))
#Initialize and send login information (defined above)
username = driver.find_element_by_id("md-input-3")
password = driver.find_element_by_id("md-input-6")
username.send_keys(crunchbase_username)
password.send_keys(crunchbase_password)
#Click login button
password.send_keys(Keys.ENTER)
#Wait for results page to finish loading
wait = WebDriverWait(driver, 15)
element = wait.until(EC.title_contains("Signals"))
time.sleep(2)
#Press Download Button
driver.find_element_by_xpath("//button[@aria-label='Export your results']").click()
time.sleep(2)
#Press csv button
driver.find_element_by_xpath("//button[@aria-label='Export to CSV']").click()
time.sleep(2)
#Confirm downlaod
driver.find_element_by_xpath("//*[@id='cdk-overlay-36']/md-dialog-container/confirmation-dialog/dialog-layout/div/md-dialog-actions/div/button[2]").click()
#Close driver
#driver.close()
The page source is overly complicated and highly stylized so I will not include it here, but a screenshot of the relevant section of the code in my browser’s web inspector is below. The element which I’m trying to click is highlighted in blue.
I appreciate any help with this.
Before clicking on the element, execute the following lines:
WebElement element = driver.findElement(By.xpath(" path_of_your_module "));
((JavaScriptExecutor) driver). executeScript("argument[0].scrollIntoView(true);", element);
It is hard to tell without having access to the page under question and being able to see what’s going. Few general points:
- Try css selectors instead of xpath. They are more robust, easier to work with and fast.
- Acvoid using dynamically generated IDs. In your screenshot I can’t even see an id that appears in your code.
- When you have more than one element of the same kind (like buttons in your case) try getting all webelements under a certain parent and test all of them for having an attribute value that you are looking for.
For example:
elemItems = driver.find_elements_by_css_selector(menuItemSelector)
for element in elements:
if element.text == "export":
elemItems[1].click()
Here, you find all the elements of a certain type (buttons for example) and select one that has “export” text in it.
I faced the same issue on a dialogOverlay and I fixed it. I realized that on clicking the overlay button that would bring the overlay, selenium was searching for the element before the overlay loads the dynamic content. So I did this:
def download():
global browser
notFound = True
while(notFound):
try:
elem = browser.find_element(By.ID, 'btnFormat2')
elem.click()
notFound = False
except BaseException:
print("----Error Download Element not found")
download()
The code will continuously look for the element until its loaded on the overlay.