ElementNotInteractableException in Selenium when trying to automate browser - python

When I am trying to enter the input in the given field I get an error saying
selenium.common.exceptions.ElementNotInteractableException: Message: Element <input class="text-input email-input js-signin-email" name="session[username_or_email]" type="text"> is not reachable by keyboard
I tried increasing the timer.sleep() from 10 seconds to 15 seconds. I found no fix.

Use explicit wait instead:
from selenium.webdriver.support import ui
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By
input_filed = ui.WebDriverWait(driver, 10).until(
EC.element_to_be_clickable((By.CSS_SELECTOR, "input.text-input.email-input.js-signin-email")))
# Do actions with input element.
Hope it helps you!

Related

Using Selenium to accept a splash page

When I load the my site as shown below, a splash screen appears to confirm I am 21 years of age. I am trying to load the element to click yes, but I am unable to bypass the age verification screen.
My approach was to load the page. Add a sleep time, find the element and click Yes. However it wont work.
driver.get('https://seelbachs.com/products/sagamore-spirit-cask-strength-rye-whiskey')
time.sleep(5)
element= driver.find_element_by_xpath('//*[#id="enter"]')
element.click()
Error received.
selenium.common.exceptions.NoSuchElementException: Message: no such element: Unable to locate element: {"method":"xpath","selector":"//*[#id="enter"]"}
So either my find.element is off or my time.sleep is not helping with the splash page.
It seems the problem is that the pop-up is in an iframe.
This code appears to do the trick
from selenium import webdriver
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By
from selenium.common.exceptions import NoSuchElementException
from selenium.webdriver import ActionChains
import time
driver = webdriver.Chrome('/usr/local/bin/chromedriver')
driver.get('https://seelbachs.com/products/sagamore-spirit-cask-strength-rye-whiskey')
# xpath of iframe
frame_xpath = '/html/body/div[5]/div/div/div/div/iframe'
wait = WebDriverWait(driver, 10)
# wait until iframe appears and select iframe
wait.until(EC.frame_to_be_available_and_switch_to_it((By.XPATH, frame_xpath)))
# select button
xpath = '//*[#id="enter"]'
time.sleep(2)
element= driver.find_element_by_xpath(xpath)
ActionChains(driver).move_to_element(element).click(element).perform()
referencing This answer on Stack Overflow
You need to switch to the frame, check the below code
driver.get('https://seelbachs.com/products/sagamore-spirit-cask-strength-rye-whiskey')
sleep(5)
driver.switch_to.frame(driver.find_element_by_xpath("//iframe[contains(#id,'fancyboxAge-frame')]"))
OR
#Using the explicitWait
WebDriverWait(driver,10).until(EC.frame_to_be_available_and_switch_to_it((By.XPATH,"//iframe[contains(#id,'fancyboxAge-frame')]")))
element= driver.find_element_by_xpath('//*[#id="enter"]')
element.click()
import
from time import sleep
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.wait import WebDriverWait

ElementNotInteractableException: Message: Element is not reachable by keyboard

I have the following snippet of JS code in a form that I want to use Selenium to input:
<oj-input-password id="idcs-signin-basic-signin-form-password" data-idcs-placeholder-translation-id="idcs-password-placeholder" class="oj-sm-12 oj-inputpassword oj-form-control oj-component oj-complete" value="{{password}}" placeholder="[[bundle('signin.password')]]" labelled-by="ui-id-2"><input data-oj-internal="" type="password" placeholder="Password" class="oj-inputpassword-input oj-component-initnode" id="idcs-signin-basic-signin-form-password|input"></oj-input-password>
I'm trying to enter the password:
password = browser.find_element_by_id('idcs-signin-basic-signin-form-password')
password.send_keys("my_password")
But then I get the following error:
selenium.common.exceptions.ElementNotInteractableException: Message: Element <oj-input-password id="idcs-signin-basic-signin-form-password" class="oj-sm-12 oj-inputpassword oj-form-control oj-component oj-complete"> is not reachable by keyboard
Why does this happen and what's the workaround?
Import explicit wait:
from selenium.webdriver.common.by import By
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
Use it this way:
wait = WebDriverWait(driver, 15)
wait.until(EC.element_to_be_clickable(
(By.CSS_SELECTOR, "#idcs-signin-basic-signin-form-password")))
And use CSS selector instead of id:
password = browser.find_element_by_css_selector("#idcs-signin-basic-signin-form-password")
password.send_keys("my_password")
# indicates an element id.
Also, check for the conditions:
element is not iframe
element is not in shadow DOM.
I would suggest you to use ActionChains
from selenium.webdriver.common.action_chains import ActionChains
ActionChains(driver).move_to_element(driver.find_elements_by_css_selector("input[type='password'][placeholder='Password']")).send_keys('your password').perform()
also make sure to launch browser in full screen mode. and if scrolling is required, I would suggest you to do that as well.

Message: no such element: Unable to locate element: {"method":"xpath","selector":"/html/body/div[2]/div[2]/div/div[3]/div[2]/div/div/div[2]/a[1]"}

from selenium import webdriver
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.support.ui import Select
import time
print('\n')
print("PROGRAM STARTING")
print('~~~~~~')
print('\n')
# initiate driver
driver = webdriver.Chrome()
driver.get('http://arcselfservice.sbcounty.gov/web/user/disclaimer')
#begin
driver.find_element_by_xpath('//*[#id="submitDisclaimerAccept"]').click()
driver.find_element_by_xpath('/html/body/div[2]/div[2]/div/div[3]/div[2]/div/div/div[2]/a[1]').click()
I have been stuck on this error for a long time, for some reason it can't find the element even though I am specifying the xpath. There doesn't seem to be any iframes, and implicit or explicit wait doesn't work either. Please help.
So the issue was waiting for the element to come up and then clicking it.
WebDriverWait(driver, 10).until(EC.element_to_be_clickable((By.XPATH, "/html/body/div[2]/div[2]/div/div[3]/div[2]/div/div/div[2]/a[1]"))).click()
Another way if you want to change to the other tags later.
path = "//a/div/h1[text()='{}']/../..".format("Fictitious Business Names Application")
WebDriverWait(driver, 10).until(EC.element_to_be_clickable((By.XPATH ,path))).click()
Import
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
The error is coming because the element is taking time to be available for use. Kindly use the explicit wait for the element extraction.
A small snippet can be:
WebDriverWait(driver, 10).until(EC.presence_of_element_located((By.XPATH ,'/html/body/div[2]/div[2]/div/div[3]/div[2]/div/div/div[2]/a[1]'))).click()
Just dont forget to import
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By

How to wait till page loads and then press the load more button in selenium?

Using selenium to load and page and need to click load more button, but after it clicks load more than 100 times
i m getting this error of element click intercepted. because after 100 times the page takes time to load. and code doesnt know where to click.
Tried increasing sleep time to 20 seconds also but at some points if page takes more than 20 seconds the code returns error
error :
ElementNotInteractableException: Message: element not interactable (Session info: chrome=75.0.3770.100)
code :
from selenium import webdriver
import time
import pandas as pd
driver = webdriver.Chrome('/Users/1/chromedriver.exe')
driver.get('https://simpletire.com/catalog?select=1&brand=61&query=catalog')
click_more=True
while click_more:
time.sleep(2)
driver.find_element_by_css_selector(".btn.btn-primary.btn-lg").click();
Consider introducing Explicit Wait to ensure that the button is there prior to attempting clicking it
Example code:
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
driver = webdriver.Chrome('/Users/1/chromedriver.exe')
driver.get('https://simpletire.com/catalog?select=1&brand=61&query=catalog')
click_more=True
while click_more:
WebDriverWait(driver, 30).until(EC.presence_of_element_located((By.CSS_SELECTOR, ".btn.btn-primary.btn-lg"))).click()
More information:
Python Selenium: Wait Support
Python Selenium: Waits
How to use Selenium to test web applications using AJAX technology
In these situations I typically stop the page load, perhaps scroll a couple of times and use screen coordinates with a macro tool like AppRobotic to click the button. Something like this should work for you:
import win32com.client
from win32com.client import Dispatch
x = win32com.client.Dispatch("AppRobotic.API")
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
driver = webdriver.Chrome('/Users/1/chromedriver.exe')
driver.get('https://simpletire.com/catalog?select=1&brand=61&query=catalog')
# wait 20 seconds per question
x.Wait(20000)
# scroll down a couple of times in case page javascript is waiting for user interaction
x.Type("{DOWN}")
x.Wait(2000)
x.Type("{DOWN}")
x.Wait(2000)
# forcefully stop pageload at this point
driver.execute_script("window.stop();")
# if clicking with Selenium still does not work here, use screen coordinates
x.MoveCursor(xCoord, yCoord)
x.MouseLeftClick
x.Wait(2000)
It would appear that you might be running into the google ad at the bottom of the page.
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.common.exceptions import TimeoutException
driver = webdriver.Chrome()
driver.get('https://simpletire.com/catalog?select=1&brand=61&query=catalog')
click_more=True
wait = WebDriverWait(driver, 30)
while click_more:
try:
elem = wait.until(EC.visibility_of_element_located((By.XPATH, '//button[#class="btn btn-primary btn-lg"]')),
"Cannot find 'Load More' button")
elem.click()
except TimeoutException:
click_more = False
Using xpath and visibility_of_element_located I get the following exception:
selenium.common.exceptions.ElementClickInterceptedException: Message: element click intercepted: Element <button class="btn btn-primary btn-lg">...</button> is not clickable at point (591, 797). Other element would receive the click: <iframe id="google_ads_iframe_/21692090825/ST_FlexFooter_0" title="3rd party ad content" name="google_ads_iframe_/21692090825/ST_FlexFooter_0" width="970" height="90" scrolling="no" marginwidth="0" marginheight="0" frameborder="0" srcdoc="" style="border: 0px; vertical-align: bottom;" data-google-container-id="1" data-load-complete="true"></iframe>
You either need to close the google add or scroll the page down a little before attempting to click the button. Once that is done, the while loop should work.
Try the script below to keep clicking on that button until there is none left to click.
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.common.exceptions import TimeoutException
from selenium.webdriver.support import expected_conditions as EC
with webdriver.Chrome() as driver:
wait = WebDriverWait(driver, 10)
driver.get('https://simpletire.com/catalog?select=1&brand=61&query=catalog')
while True:
try:
item = wait.until(EC.visibility_of_element_located((By.CSS_SELECTOR, "#load_button > button")))
except TimeoutException:
item = ""
if not item: break
driver.execute_script("arguments[0].scrollIntoView();", item)
item.click()

Wait until loader disappears python selenium

<div id="loader-mid" style="position: absolute; top: 118.5px; left: 554px; display: none;">
<div class="a">Loading</div>
<div class="b">please wait...</div>
</div>
And want to wait until it disappears. I have following code but it wait sometimes too long and at some point of code it suddenly freeze all process and I don't know why.
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By
from selenium.webdriver.support.wait import WebDriverWait
self.wait = WebDriverWait(driver, 10)
self.wait.until(EC.invisibility_of_element_located((By.XPATH, "//*[#id='loader_mid'][contains(#style, 'display: block')]")))
and also I tried this one:
self.wait.until_not(EC.presence_of_element_located((By.XPATH, "//*[#id='loader_mid'][contains(#style, 'display: block')]")))
I don't know exactly how to check but maybe my element is always present on the page and selenium thought that it is there, the only thing that changes is parameter display changes from none to block. I think I can get attribute like string and check if there is word "block" but it is so wrong I thing... Help me please.
Reiterated your answer (with some error handling) to make it easier for people to find the solution :)
Importing required classes:
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.wait import WebDriverWait
Configuration variables:
SHORT_TIMEOUT = 5 # give enough time for the loading element to appear
LONG_TIMEOUT = 30 # give enough time for loading to finish
LOADING_ELEMENT_XPATH = '//*[#id="xPath"]/xPath/To/The/Loading/Element'
Code solution:
try:
# wait for loading element to appear
# - required to prevent prematurely checking if element
# has disappeared, before it has had a chance to appear
WebDriverWait(driver, SHORT_TIMEOUT
).until(EC.presence_of_element_located((By.XPATH, LOADING_ELEMENT_XPATH)))
# then wait for the element to disappear
WebDriverWait(driver, LONG_TIMEOUT
).until_not(EC.presence_of_element_located((By.XPATH, LOADING_ELEMENT_XPATH)))
except TimeoutException:
# if timeout exception was raised - it may be safe to
# assume loading has finished, however this may not
# always be the case, use with caution, otherwise handle
# appropriately.
pass
Use expected condition : invisibility_of_element_located
This works fine for me.
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.wait import WebDriverWait
WebDriverWait(driver, timeout).until(EC.invisibility_of_element_located((By.ID, "loader-mid")))
The following code creates an infinite loop until the element disappears:
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.common.exceptions import TimeoutException
while True:
try:
WebDriverWait(driver, 1).until(EC.presence_of_element_located((By.XPATH, 'your_xpath')))
except TimeoutException:
break
Ok, here is how i solved this issue for my project,
imports
from selenium.common.exceptions import TimeoutException
from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.common.by import By
from selenium.webdriver.support.wait import WebDriverWait as wait
Now the code part
browser = webdriver.Chrome(service=Service("./chromedriver.exe"))
browser.get("https://dashboard.hcaptcha.com/signup?type=accessibility")
try:
d = wait(browser, 10).until(EC.invisibility_of_element_located((By.ID, 'loader-mid')))
if d: # just a check you can ignore it.
print("yes")
sleep(3)
else:
print("F")
except TimeoutException:
print("timeout error occurred.")
pass
browser.quit()
Or you can use Implicit wait
driver.implicitly_wait(10) # seconds
# do something after...

Categories

Resources