acc = self.wait.until(EC.visibility_of_element_located((By.XPATH,"//tr[#valign='top']/td[2]/input[#id='account']")))
acc.send_keys(user['userid'])
time.sleep(1)
pwd = self.wait.until(EC.visibility_of_element_located((By.XPATH, "//tr[#valign='bottom']/td/input[#id='passwordInput1']")))
pwd.send_keys(user['pwd'])
I tried to login to a website and i can successfully input the account name--that is "acc" in the codes, but when it came the pwd, it will display an error message. And i tested that the pwd element can be fine, only the send_keys line went wrong.
selenium.common.exceptions.ElementNotInteractableException: Message: Element <input id="passwordInput1" class="inputField1" name="passwordInput1" type="text"> is not reachable by keyboard
It occurred in geckodriver and chromedrive, but was okay with phantomjs. Anyone knows what's happening?
The keyboard is not available at that time.It mean that using a keyboard is not effective.The situation I've encountered is that the page has changed, and the popup window, for example, alter.You should use :
driver.save_screenshot('screen.png')
try:
pwd = self.wait.until(
EC.visibility_of_element_located((By.XPATH, "//tr[#valign='bottom']/td/input[#id='passwordInput1']")))
pwd.send_keys(user['pwd'])
except Exception as e:
print(e)
driver.save_screenshot('screen.png')
to see the page status at that time.
You could try sending text by action chains:
import selenium.webdriver.common.actions
ActionChains(driver).send_keys_to_element(element, password).perform()
Where:
driver is the driver you are using,
element is your located element,
password is the text you want to send.
This solved my similar issue.
Docs:
https://selenium-python.readthedocs.io/api.html#module-selenium.webdriver.common.action_chains
Related
How should I check if the following is working? What can I do, to get a true or false response?
driver.find_element_by_link_text("XXXX").click()
let's say when you fire a .click event, a event occurs in UI (for an example after clicking on login button, we see dashboard page title or heading)
what we would do in this case is to assert that heading, or title, if assertion works then script will get to know that the previous .click was actually done, cause if it was not then assertion would have failed.
try:
driver.find_element_by_link_text('some text').click()
# put some delay here, WebDriverWait or time.sleep()
assert driver.find_element_by_xpath('dashboard page heading web xpath here').text in "expected dashboard heading"
print('Assertion worked so .click was correct')
except:
print('Assertion must have failed')
Clicking on a link typically takes you to another window/tab. You can capture the title/url of that page and assert that click operation worked
try:
ele=driver.find_element_by_link_text("XXXX")
if (ele):
print "this link exists in the page"
except:
print("there is no such link in the page")
I know that multiple people have asked a similar question about this however, I would like to know how to login to gmail (or google account) using python. I have a code already (see below) that can loggin the user to gmail using selenium. However I noticed a few problems.
The browser closes when the program stops/closes.
It can not detect a failed login.
Both problems really need to be solved for me to be able to work on my project. I don't mind using something else than selenium like pyautogui to open google. However, it needs to be able to detect a failed login and then close the browser, if the login is successful the browser should stay open for the user to use.
My code:
from selenium import webdriver
from webdriver_manager.chrome import ChromeDriverManager
def gmail_login(username, password):
gmailId = username
passWord = password
driver = webdriver.Chrome(ChromeDriverManager().install())
try:
driver.get(r'https://accounts.google.com/signin/v2/identifier?continue=' + \
'https%3A%2F%2Fmail.google.com%2Fmail%2F&service=mail&sacu=1&rip=1' + \
'&flowName=GlifWebSignIn&flowEntry = ServiceLogin')
driver.implicitly_wait(3)
loginBox = driver.find_element_by_xpath('//*[#id ="identifierId"]')
loginBox.send_keys(gmailId)
nextButton = driver.find_elements_by_xpath('//*[#id ="identifierNext"]')
nextButton[0].click()
passWordBox = driver.find_element_by_xpath(
'//*[#id ="password"]/div[1]/div / div[1]/input')
passWordBox.send_keys(passWord)
nextButton = driver.find_elements_by_xpath('//*[#id ="passwordNext"]')
nextButton[0].click()
except:
driver.close()
gmail_login("email#gmail.com", "Password")
I tought of checking the url after the program has finished if it is equal to a logged in url however that didn't really work too well and now I am out of ideas.
Updated 02-14-2021
I was able to extract this error message:
using this code:
signin_failure = driver.find_elements_by_xpath("//*[contains(text(),'Couldn’t sign you in')]")
if signin_failure[1].text == 'Couldn’t sign you in':
print('something went wrong')
In a normal gmail login you will get one of these two error messages:
Couldn’t find your Google Account
Wrong password. Try again or click Forgot password to reset it
The XPATH to get these error messages is:
wrong_email = driver.find_elements_by_xpath("//*[contains(text(),'Couldn’t find your Google Account')]")
wrong_password = driver.find_elements_by_xpath("//*[contains(text(),'Wrong password. Try again or click Forgot password to reset it')]")
if you want to close the browser after an error message, such as Couldn’t sign you in then add a driver.close() statement.
signin_failure = driver.find_elements_by_xpath("//*[contains(text(),'Couldn’t sign you in')]")
if signin_failure[1].text == 'Couldn’t sign you in':
print('something went wrong')
driver.close()
If you want to keep the browser open then don't use the driver.close() statement, but add this experimental_option
chrome_options.add_experimental_option("detach", True)
I was also able to throw these error messages:
signin_failure = driver.find_elements_by_xpath("//*[contains(text(),'Couldn’t sign you in')]")
# this message was throw when the next button was clicked prior to entering a username
no_input = driver.find_elements_by_xpath("//*[contains(text(),'Enter a valid email of phone number')]")
PSEUDOCODE CODE:
This is how you could do it, but you might have to adjust the code as you test.
def gmail_login(username, password):
driver = webdriver.Chrome(ChromeDriverManager().install())
try:
driver.get(r'https://accounts.google.com/signin/v2/identifier?continue=' + \
'https%3A%2F%2Fmail.google.com%2Fmail%2F&service=mail&sacu=1&rip=1' + \
'&flowName=GlifWebSignIn&flowEntry = ServiceLogin')
driver.implicitly_wait(3)
loginBox = driver.find_element_by_xpath('//*[#id ="identifierId"]')
loginBox.send_keys(username)
nextButton = driver.find_elements_by_xpath('//*[#id ="identifierNext"]')
nextButton[0].click()
wrong_email = driver.find_elements_by_xpath("//*[contains(text(),'Couldn’t find your Google Account')]")
# you need to check this slice
if wrong_email[1].text == 'Couldn’t find your Google Account':
print('something went wrong')
driver.close()
else:
passWordBox = driver.find_element_by_xpath('//*[#id ="password"]/div[1]/div / div[1]/input')
passWordBox.send_keys(password)
nextButton = driver.find_elements_by_xpath('//*[#id ="passwordNext"]')
nextButton[0].click()
wrong_password = driver.find_elements_by_xpath("//*[contains(text(),'Wrong password. Try again or click Forgot password to reset it')]")
# you need to check this slice
if wrong_password[1].text == 'Wrong password. Try again or click Forgot password to reset it':
print('something went wrong')
driver.close()
except:
driver.close()
Original post
Google forbids using automated scripts for logging into Gmail. I have tried using selenium and I get this warning.
When I click Learn More I get this message.
Please note this line: Are being controlled through software automation rather than a human
Here are other question where they discuss work arounds for this Google direct login issue:
“This browser or app may not be secure” error while attempting to login in to Gmail account using Selenium
GMail is blocking login via Automation (Selenium)
You should be looking at the Gmail API for programmatic access, it will work a lot better than trying to drive the UI like selenium does.
https://developers.google.com/gmail/api/quickstart/python
I have no time right now to code, but:
To make your browser stay open just delete your driver.close() function, this is what makes it to stop when program reach it.
To solve your problem, just try to make a successfull login and a failing one, look for a WebElement in both that indicates one of the events in an unique way, then, put the driver.close() in an if declaration only if selenium finds the WebElement in viewport after the login (failed one), otherwise do not let it execute the instruction.
Easy as that.
I am trying to log in to my amboss account using Selenium webdriver with python, but as I dont have much experience with it I dont understand what goes wrong. My credentials (email and password) are correct as I have used them to log into the website before.
Here is my code so far:
# run firefox webdriver from executable path
driver = webdriver.Firefox(firefox_options=options, capabilities=cap, executable_path = path_to_driver)
driver.get("https://www.amboss.com/us/account/login")
signinusername = config['amboss']['email']
signinpassword= config['amboss']['password']
username = driver.find_element_by_id("signin_username")
username.clear()
username.send_keys(signinusername)
pwd = driver.find_element_by_xpath("//*[#id='signin_username']")
pwd.clear()
pwd.send_keys(signinpassword)
loginbutton = driver.find_element_by_xpath("/html/body/div[2]/div[1]/div/div/form/div[4]/input").click()
time.sleep(20)
# execute script to scroll down the page
driver.execute_script("window.scrollTo(0, document.body.scrollHeight);var lenOfPage=document.body.scrollHeight;return lenOfPage;")
#element in log in page
newelement = driver.find_element_by_xpath("//*[#id='left']/p[1]/strong")
print(newelement.get_attribute('innerHTML'))
What I try to do here is log in to the platform and then grab an element which I see in the welcome page by xpath. Despite that selenium is unable to find this element and I get the following error:
selenium.common.exceptions.NoSuchElementException: Message: Unable to locate element: //*[#id='left']/p[1]/strong
Does anyone understand why this happens? Is it because log in was not successful or could something else be wrong? Thanks in advance
UPDATE
The elements you were trying to fetch were in an iframe so you need to switch to that iframe so they be visible. The following works, try it.
username = driver.find_element_by_id("signin_username")
username.clear()
username.send_keys(signinusername)
pwd = driver.find_element_by_id('signin_password')
pwd.clear()
pwd.send_keys(signinpassword)
loginbutton = driver.find_element_by_class_name('amboss-button').click()
time.sleep(2)
driver.execute_script("window.scrollTo(0, document.body.scrollHeight);var lenOfPage=document.body.scrollHeight;return lenOfPage;")
time.sleep(2)
frames = driver.find_elements_by_tag_name('iframe')
driver.switch_to.frame(frames[4])
newelement = driver.find_elements_by_tag_name('p')[0].text # This prints the following 'You now have access to AMBOSS—an all-in-one pl....'
print(newelement)
I'm assuming you're trying to login to the system and trying to find something.
First of all your login attempt is not correct. You're entering password in the username field in your code.
Please do login like this:
At first, add this import to your python script:
from selenium.webdriver.common.keys import Keys
Then do login like this:
username = driver.find_element_by_id("signin_username")
username.clear()
username.send_keys(signinusername)
pwd = driver.find_element_by_id("signin_password")
pwd.clear()
pwd.send_keys(signinpassword)
pwd.send_keys(Keys.ENTER)
I'm not logging in by clicking the button. Just hitting an ENTER after logging in.
I guess correcting the login attempt will help you to find your element and print contents inside this.
I've created an account in amboss to answer your question and after logging in the only iframe I found was from google tag manager with no contents in it. So I'm not really sure if your account contains some other web views.
Hope correcting the login attempt helps.
First you wrong this is line :
pwd = driver.find_element_by_xpath("//*[#id='signin_username']")
Please change with :
pwd = driver.find_element_by_id('signin_password')
Second, use conditional if for validation success or failed login :
click login here
time.sleep(20)#here recommendation use WebDriverWait
count = len(driver.find_elements_by_xpath("//*[#id='left']/p[1]/strong"))
if count > 0:
print("login success")
print(driver.find_element_by_xpath("//*[#id='left']/p[1]/strong").text)
else:
print("login failed")
Make sure this is the correct locator : //*[#id='left']/p[1]/strong
https://gist.github.com/codyc4321/724f05aca8f6775e2fc1
Hi, bitbucket changed their login page, and is giving me a hassle. Based on the following gist, using driver.click_button causes:
ElementNotVisibleException at /bitbucket/create-repo
Message: Element is not currently visible and so may not be interacted with
Stacktrace:
at fxdriver.preconditions.visible (file:///tmp/tmpSNzLIl/extensions/fxdriver#googlecode.com/components/command-processor.js:9981)
at DelayedCommand.prototype.checkPreconditions_ (file:///tmp/tmpSNzLIl/extensions/fxdriver#googlecode.com/components/command-processor.js:12517)
at DelayedCommand.prototype.executeInternal_/h (file:///tmp/tmpSNzLIl/extensions/fxdriver#googlecode.com/components/command-processor.js:12534)
at DelayedCommand.prototype.executeInternal_ (file:///tmp/tmpSNzLIl/extensions/fxdriver#googlecode.com/components/command-processor.js:12539)
at DelayedCommand.prototype.execute/< (file:///tmp/tmpSNzLIl/extensions/fxdriver#googlecode.com/components/command-processor.js:12481)
using driver.submit_form causes error in the browser itself:
using driver.activate_hidden_element causes:
ElementNotVisibleException at /bitbucket/create-repo
Message: Element is not currently visible and so may not be interacted with
activate_hidden_element failing really took the wind outta my sails for the last 5 minutes. How can I click this stonewalling button? Thank you
Okay, so the problem is actually in your locate_element method.
When you check for the xpath: "//button[normalize-space(text())='{text}']" it finds a button successfully but it is not the login button you are looking for. If you switch that with the input xpath: "//input[#value='{text}']" it finds the right input and successfully logs you in.
You should also remove the last two lines in the BitbucketDriver.login() method because the line self.click_button(search_text="Log in") throws an AttributeError.
Your locate_element method should look like this:
def locate_element(self, search_text, xpaths=None):
if not xpaths:
xpaths = [ "//input[#value='{text}']", "//button[normalize-space(text())='{text}']",
"//a[child::span[normalize-space(text())='{text}']]", "//a[normalize-space(text())='{text}']"]
try:
return self.driver.find_element_by_id(search_text)
except:
try:
return self.driver.find_element_by_name(search_text)
except:
try:
return self.driver.find_element_by_class_name(search_text)
except:
for path in xpaths:
try:
return self.driver.find_element_by_xpath(path.format(text=search_text))
except:
pass
return None
I have a HTML code like this:
<div class="links nopreview"><span><a class="csiAction"
href="/WebAccess/home.html#URL=centric://REFLECTION/INSTANCE/_CS_Data/null">Home</a></span> • <span><span><a class="csiAction"
href="/WebAccess/home.html#URL=centric://SITEADMIN/_CS_Site">Setup</a></span> • </span><span><a
title="Sign Out" class="csiAction csiActionLink">Sign Out</a></span></div>
I would like to click on the link that has the text Home. As this Home link appears after login, I have a code like this:
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
import re
browser = webdriver.Firefox() # Get local session of firefox
browser.get("http://myServer/WebAccess/login.html") # Load App page
elem = browser.find_element_by_name("LoginID") # Find the Login box
elem.send_keys("Administrator")
elem = browser.find_element_by_name("Password") # Find the Password box
elem.send_keys("Administrator" + Keys.RETURN)
#try:
elem = browser.find_element_by_link_text("Home")
elem.click()
The part till login works great. However the last but one line is problematic
elem = browser.find_element_by_link_text("Home")
It raises this NoSuchElementException where the Home link is there as you can see from the HTML code.
raise exception_class(message, screen, stacktrace)
NoSuchElementException: Message: u'Unable to locate element: {"method":"link text","selector":"Home"}'
Any guidance as to what I am doing wrong, please?
Have you tried adding an implicit wait to this so that it waits instead of running to quickly.
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
import re
browser = webdriver.Firefox() # Get local session of firefox
browser.implicitly_wait(10) #wait 10 seconds when doing a find_element before carrying on
browser.get("http://myServer/WebAccess/login.html") # Load App page
elem = browser.find_element_by_name("LoginID") # Find the Login box
elem.send_keys("Administrator")
elem = browser.find_element_by_name("Password") # Find the Password box
elem.send_keys("Administrator" + Keys.RETURN)
#try:
elem = browser.find_element_by_link_text("Home")
elem.click()
The implicitly_wait call makes the browser poll until the item is on the page and visible to be interacted with.
The most common issues with NoSuchElementException while the element is there are:
the element is in different window/frame, so you've to switch to it first,
your page is not loaded or your method of page load is not reliable.
Solution could include:
check if you're using the right frame/window by: driver.window_handles,
write a wait wrapper to wait for an element to appear,
try XPath instead, like: driver.find_element_by_xpath(u'//a[text()="Foo"]').click(),
use pdb to diagnose your problem more efficiently.
See also: How to find_element_by_link_text while having: NoSuchElement Exception?
Maybe the element you are looking for doesn't exactly match that text string?
I know it can be tricky if it looks like it does on-screen, but sometimes there are oddities embedded like this simple markup "Home" or "Home" which makes the first char italic:
"<i>H</i>ome" is visually identical to "<em>H</em>ome" but does not match text.
Edit: after writing the above answer, I studied the question closer and discovered the HTML sample does show "Home" in plain text, but was not visible due to long lines not wrapping. So I edited the OP to wrap the line for readability.
New observation: I noticed that the Logout element has a "title" attribute, but the Home link element lacks such--try giving it one and using that.
Try adding an implicit wait to this in order to wait, instead of running too quickly.
Or
else you can import time and use time.sleep(25)