Python: Selenium "no such element" XPath or ID - python

I am attempting to log into Tessco.com
I have learned this site uses JavaScript, which is why I was unable to locate a form using RoboBrowser.
I am now using Selenium. I have used two methods to enter information into a field. One, using the driver.find_element_by_xpath()as well as driver.find_element_by_id()
Both attempts yield an error.
The code is as follows:
import time
from selenium import webdriver
chrome_path = r"C:\Users\James\Documents\Python Scripts\jupyterNoteBooks\ScrapingData\chromedriver_win32\chromedriver.exe"
driver = webdriver.Chrome(chrome_path)
driver.get("https://www.tessco.com/login")
userName = "FirstName.SurName321123#gmail.com"
password = "PasswordForThis123"
elem = driver.find_element_by_xpath("""//*[#id="userID"]""")
elem = send_keys(userName)
elem = driver.find_element_by_xpath("""//*[#id="password"]""")
elem = send_keys(password)
driver.close()
The error is:
NoSuchElementException: Message: no such element: Unable to locate element: {"method":"xpath","selector":"//*[#id="userID"]"}
When I call the element by using ID as such:
elem = driver.find_element_by_id("userID")
elem = send_keys(userName)
elem = driver.find_element_by_id("password")
elem = send_keys(password)
I get:
NoSuchElementException: Message: no such element: Unable to locate element: {"method":"css selector","selector":"[id="userID"]"}
I was under the impression I inspected the element and used the appropriate names.
Any hints or ideas what I am not doing correctly?
Solution provided below in the comments section.
Code modified to:
import time
from selenium import webdriver
#Webdriver wait functions being introduced to add a delay.
#I was running into problems, with the ID not being found
#add wait for the element to be clickable before trying send keys
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
chrome_path = r"C:\Users\James\Documents\Python Scripts\jupyterNoteBooks\ScrapingData\chromedriver_win32\chromedriver.exe"
driver = webdriver.Chrome(chrome_path)
driver.get("https://www.tessco.com/login")
userName = "FirstName.SurName321123#gmail.com"
password = "PasswordForThis123"
wait = WebDriverWait(driver, 10)
elem = wait.until(EC.element_to_be_clickable((By.ID, "userID")))
elem.send_keys(userName)
elem = wait.until(EC.element_to_be_clickable((By.ID, "password")))
elem.send_keys(password)
driver.close()

It's likely that the element is not visible at first and that causes the failure. Wait until the element is visible/clickable and then use send keys.
WebDriverWait(driver, 10).until(EC.element_to_be_clickable((By.ID, "userID"))).send_keys(userName)

I guess the element search happens before its loaded. My suggestion would try putting some wait and it should work.

Related

Python - Using Selenium to Login to Web

I cannot login to this site with Selenium.
This is the url.
https://www.burn-cycle.com/my-account/pearl-district
What I tried:
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.common.by import By
import yaml
import time
conf = yaml.full_load(open("login_details.yml"))
my_burn_email = conf["user"]["email"]
my_burn_password = conf["user"]["password"]
driver = webdriver.Chrome()
driver.get("https://www.burn-cycle.com/my-account/pearl-district")
time.sleep(1)
username = driver.find_element(By.XPATH, "//*[#id='USERNAME']")
username.send_keys(my_burn_email)
pw = driver.find_element(By.XPATH, "//*[#id='PASSWORD']")
pw.send_keys(my_burn_password)
login_button = driver.find_element(By.XPATH("//*[#id='liFormWrap']/form[1]/button")).click()
The website loads (slowly) but nothing populates. This is the output:
selenium.common.exceptions.NoSuchElementException: Message: no such element: Unable to locate element: {"method":"xpath","selector":"//*[#id='USERNAME']"}
(Session info: chrome=103.0.5060.134)
What am I doing wrong?
You need to wait for the website to load completely so that you can fetch those elements from the webpage, you can achieve this by using implicitly.wait(#amount of second) command right after initializing the web driver.
driver = webdriver.Chrome()
driver.implicitly_wait(15) # gives an implicit wait for 15 seconds
the element is under iframe, you need try this way, first switch into iframe,
see this link
driver.get("https://www.burn-cycle.com/my-account/pearl-district")
time.sleep(5)
iframe = driver.find_element(By.XPATH, "//*[#id='sf-frame']")
# switch to selected iframe
driver.switch_to.frame(iframe)
username = driver.find_element(By.XPATH, "//input[#data-val-required='Username is required']")
username.send_keys("test")

How to handle hyphen (-) in html tagname in selenium python?

I'm getting the error:
no such element: Unable to locate element: {"method":"css selector","selector":"[id="mat-input-3"]"}
I tried the following commands but failed:
email_field = driver.find_element(By.ID, "mat-input-3").send_keys("Admin")
email_field = driver.find_element(By.XPATH, "//*[#id='mat-input-0']").send_keys("Admin")
Code:
from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.common.by import By
service_obj = Service("E:\Bilal Heuristify Office work\Python Automation\Tools\Chrome webdriver\chromedriver.exe")
driver = webdriver.Chrome(service = service_obj)
driver.maximize_window()
driver.get("https://charms-qa.cognitivehealthintl.com/Authorize/")
# email_field = driver.find_element(By.ID, "mat-input-3").send_keys("Admin")
email_field = driver.find_element(By.XPATH, "//*[#id='mat-input-0']").send_keys("Admin")
Your XPath is fine.
The problem is that the body of the web page, including the element you're searching for, is generated by JavaScript. Your Selenium code needs to wait until the element is ready.
See https://selenium-python.readthedocs.io/waits.html
#Bilal Ahmed, seems your locator is fine. It is just that you need to wait for the element to appear before taking action. So if you can replace the find_element part with the following two lines, it should work.
username = WebDriverWait(driver, 10)\
.until(expected_conditions.visibility_of_element_located((By.XPATH, "//*[#id='mat-input-0']")))
username.send_keys("Admin").
Also please add the following two imports for it to work.
from selenium.webdriver.support import expected_conditions
from selenium.webdriver.support.wait import WebDriverWait

How to make Selenium click on this button?

I am trying to extract all articles on this web page, but i can't make Selenium click on the "Continue" button at the end of the page.
I have tried a lot of different versions, but i'll post just the one, which at least doesn't throw an error...:
import time
from selenium import webdriver
from selenium.webdriver.common.action_chains import ActionChains
addr = 'https://www.armani.com/de/armanicom/giorgio-armani/f%C3%BCr-ihn/alle-kleidungsstucke'
options = webdriver.ChromeOptions()
options.add_argument("--enable-javascript")
driver = webdriver.Chrome(options=options)
driver.get(addr)
ContinueButton = driver.find_element_by_xpath("//li[#class='nextPage']")
# gives: No error, but also no effect
# ContinueButton = driver.find_element_by_xpath("/html/body/div[3]/main/section/div[2]/div[1]/ul/li[8]/a/span[2]")
# gives: NoSuchElementException: no such element: Unable to locate element: {"method":"xpath","selector":"/html/body/div[3]/main/section/div[2]/div[1]/ul/li[8]/a/span[2]"}
#ContinueButton = driver.find_element_by_css_selector(".nextPage > a:nth-child(1)")
# gives: NoSuchElementException: no such element: Unable to locate element:
ActionChains(driver).move_to_element(ContinueButton).click()
time.sleep(5)
Chrome engine is v86, but i have tried (and failed) with Firefox as well.
You want to wait for the element to be clickable and then attempt to click on it:
I
import time
from selenium import webdriver
from selenium.webdriver.common.action_chains import ActionChains
addr = 'https://www.armani.com/de/armanicom/giorgio-armani/f%C3%BCr-ihn/alle-kleidungsstucke'
options = webdriver.ChromeOptions()
options.add_argument("--enable-javascript")
driver = webdriver.Chrome(options=options)
driver.get(addr)
ContinueButton = WebDriverWait(driver, 20).until(
EC.element_to_be_clickable((By.XPATH, "//li[#class='nextPage']/a")))
ActionChains(driver).move_to_element(ContinueButton).click()
time.sleep(5)
The problem is that you are clicking on the li element.
Your click is received but no action is performed, in order to do so you need to target the a element after the li.
Try this:
ContinueButton = driver.find_element_by_xpath("//li[#class='nextPage']/a")

Problems logging in to site with Selenium

I'm trying to learn how to use Selenium to log into a site:Ingram-Micro. I made a script and it worked on a different page: https://news.ycombinator.com/login.
Now I'm trying to apply the same thing to Ingram-Micro and I'm stuck and I don't know what else to try. The problem I'm having is a error/message that says the submit element is not clickable, there is a accept cookies button on the bottom of the page which seems to be causing the problem.
I've tried to account for it but I always get error saying that element doesn't exist. Yet if I don't try to click on the accept cookies element I get the original error saying the submit button isn't clickable. Here is my code:
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from selenium.common.exceptions import NoSuchElementException
import time
chrome_options = Options()
chrome_options.add_argument('--headless')
chrome_options.add_argument('--no-sandbox')
url = "https://usa.ingrammicro.com/_layouts/CommerceServer/IM/Login.aspx?
returnurl=//usa.ingrammicro.com/"
driver = webdriver.Chrome(options=chrome_options)
driver.get(url)
def login():
USERNAME = 'email'
PASSWORD = 'password'
element = driver.find_element_by_link_text('I ACCEPT')
if element.is_displayed():
print("Element found")
element.click()
else:
print("Element not found")
driver.find_element_by_id('okta-signin-username').send_keys(USERNAME)
driver.find_element_by_id('okta-signin-password').send_keys(PASSWORD)
driver.find_element_by_id('okta-signin-submit').click()
login()
try:
me = driver.find_element_by_id("login_help-about")
print(f"{me.text} Element found")
except NoSuchElementException:
print('Not found')
driver.quit()
Here are the errors I get:
selenium.common.exceptions.ElementClickInterceptedException: Message: element click intercepted: Element <input class="button button-primary" type="submit" value="Log in" id="okta-signin-submit" data-type="save"> is not clickable at point (365, 560). Other element would receive the click: <p class="cc_message">...</p>
selenium.common.exceptions.NoSuchElementException: Message: no such element: Unable to locate
element: {"method":"link text","selector":"I ACCEPT"}
(Session info: headless chrome=84.0.4147.125)
The challenge you face is synchronisation around scripts.
The chain of events on this site is 1) the page is loaded, 2) it kicks off it's javascript, 3) that slides the cookie window into view...
However, after the page is loaded, selenium doesn't know about the scripts so it thinks it is good to go. It's trying to click the button before it's there and gets upset that it can't find it. (NoSuchElementException)
There are different sync strategies - What works here is a webdriverwait to tell selenium to wait (without error) until that your object reached the specified expected conditions.
You can read more about waits and expected conditions here
Try this code.
For the cookie "I ACCEPT" button, I changed the identifier to xpath (since i like xpaths) and wrapped it in webdriverwait, waiting for the object to be clickable...
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from selenium.common.exceptions import NoSuchElementException
import time
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By
chrome_options = Options()
#chrome_options.add_argument('--headless')
chrome_options.add_argument('--no-sandbox')
url = "https://usa.ingrammicro.com/_layouts/CommerceServer/IM/Login.aspx?returnurl=//usa.ingrammicro.com/"
driver = webdriver.Chrome(options=chrome_options)
driver.get(url)
def login():
USERNAME = 'email'
PASSWORD = 'password'
element = WebDriverWait(driver, 30).until(EC.element_to_be_clickable((By.XPATH, '//a[text()="I ACCEPT"]')))
if element.is_displayed():
print("Element found")
element.click()
else:
print("Element not found")
driver.find_element_by_id('okta-signin-username').send_keys(USERNAME)
driver.find_element_by_id('okta-signin-password').send_keys(PASSWORD)
driver.find_element_by_id('okta-signin-submit').click()
login()
Note that i had to remove headless to check it worked and there are 3 additional imports at the top.
Webdriverwait is great when you don't have lots of complicated objects, or have ojects with different wait conditions.
An alternative sync and (Easier in my opionin) is to set an implicit wait ONCE at the start of your script - and this configures the driver objecct.
driver.implicitly_wait(10)
As that link earlier says:
An implicit wait tells WebDriver to poll the DOM for a certain amount
of time when trying to find any element (or elements) not immediately
available. The default setting is 0. Once set, the implicit wait is
set for the life of the WebDriver object.
You can use it like this .. not doing all the code, just add this one line added after you create your driver and your code worked:
.....
url = "https://usa.ingrammicro.com/_layouts/CommerceServer/IM/Login.aspx?returnurl=//usa.ingrammicro.com/"
driver = webdriver.Chrome(options=chrome_options)
driver.get(url)
driver.implicitly_wait(10) # seconds
def login():
USERNAME = 'email'
PASSWORD = 'password'
element = driver.find_element_by_link_text('I ACCEPT')
if element.is_displayed():
print("Element found")
element.click()
else:
print("Element not found")
........
You probably need to click on the div above the input. try somethin like this:
child = driver.find_element_by_id('okta-signin-submit')
parent = child.find_element_by_xpath('..') # get the parent
parent.click() # click parent element
UPDATE: This worked great on geckodrive without headless, but not with chromedrive. so instead i've tried something else. Instead of clicking the button, lets just hit enter in the form and submit it this way:
from selenium.webdriver.common.keys import Keys
...
driver.find_element_by_id('okta-signin-username').send_keys(USERNAME)
password_field = driver.find_element_by_id('okta-signin-password')
password_field.send_keys(PASSWORD)
password_field.send_keys(Keys.RETURN)

ElementNotInteractableException: Message: element not interactable error while sending text to Email field on Quora using Selenium with Python

Here is my code:
from selenium import webdriver
user = "someemail#email.com"
browser = webdriver.Chrome("/path/to/browser/")
browser.get("https://www.quora.com/")
username = browser.find_element_by_name("email")
browser.implicitly_wait(10)
username.send_keys(user)
Here is the error message:
selenium.common.exceptions.ElementNotInteractableException: Message: element not interactable
I think there is another thread with a similar issue. Either the solutions in that thread didn't work for me or I don't know how to implement the solutions.
find_element_by_name("email")
is present multiple times in DOM. So that wouldn't work.
You can try with this css selector :
input[class*='header_login_text_box'][name='email']
Code :
username = browser.find_element_by_css_selector("input[class*='header_login_text_box'][name='email']")
username.send_keys("user#gmail.com")
To send a character sequence to the Email field within Login section of Quora you need to induce WebDriverWait for the element to be clickable and you can use the following solution:
Code Block:
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
options = webdriver.ChromeOptions()
options.add_argument("start-maximized")
options.add_argument("--disable-extensions")
# options.add_argument('disable-infobars')
driver = webdriver.Chrome(chrome_options=options, executable_path=r'C:\Utility\BrowserDrivers\chromedriver.exe')
driver.get("https://www.quora.com/")
WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.XPATH, "//div[#class='title login_title' and text()='Login']//following::div[1]//input[#class='text header_login_text_box ignore_interaction']"))).send_keys("someemail#email.com")
Browser Snapshot:
As said in comment, the locator used returning two elements and required element is second one. driver trying to interact with first element, so exception is throwing.
good see in console, the locator returning required one or not.
> $$("[name='email']") (2) [input#__w2_wD9e9Qgz12_email.text, input#__w2_wD9e9Qgz18_email.text.header_login_text_box.ignore_interaction]
> 0: input#__w2_wD9e9Qgz12_email.text 1:
> input#__w2_wD9e9Qgz18_email.text.header_login_text_box.ignore_interaction
> length: 2
> __proto__: Array(0)
go for another locator, if not able to figure it out another locator, then comment, will help you.
from selenium import webdriver
user = "someemail#email.com"
browser = webdriver.Chrome("/path/to/browser/")
browser.get("https://www.quora.com/")
username = browser.find_element_by_xpath("//input[#class='text header_login_text_box ignore_interaction' and #type='text']")
browser.implicitly_wait(10)
username.send_keys(user)
Here You can find Why ElementNotInteractableException occurs.
If you are using the Select aproach like:
from selenium.webdriver.support.select import Select
try this
Select(WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.XPATH, '''//*[#id="ReportViewer1_ctl04_ctl07_ddValue"]''')))).select_by_visible_text(str(x))

Categories