Selenium element is not reachable by keyboard - python

I am attempting to log into my Google account using selenium in python. I keep coming across the following error:
selenium.common.exceptions.ElementNotInteractableException: Message: Element <input class="whsOnd zHQkBf" name="password" type="password"> is not reachable by keyboard
I've looked at some other similar questions, but most of them are about failed authentication. Another post suggested looking for something covering it but I didn't see anything. Also, the input box is not hidden as per its html:
<input type="password" class="whsOnd zHQkBf" jsname="YPqjbf" autocomplete="current-password" spellcheck="false" tabindex="0" aria-label="Enter your password" name="password" autocapitalize="off" dir="ltr" data-initial-dir="ltr" data-initial-value="" badinput="false">
I've also tried putting some wait statements before accessing the password input box with no luck.
I also checked to make sure there was only 1 element being returned by the find_elemnt_by function.
To make sure I was doing it properly I tested it with Amazon and it worked perfectly, so not sure why Google's is being difficult.
Here is my code:
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
# create a new Firefox session
driver = webdriver.Firefox(executable_path="D:\Selenium\geckodriver.exe")
driver.implicitly_wait(5)
# Navigate to youtube
driver.get("https://www.youtube.com/")
sign_in_button = driver.find_element_by_css_selector('ytd-button-renderer.style-scope:nth-child(5)')
sign_in_button.click()
username = driver.find_element_by_css_selector('#identifierId')
username.send_keys('johndoe#gmail.com')
next_button = driver.find_element_by_css_selector('#identifierNext')
next_button.click()
password_text_box = driver.find_element_by_css_selector('.I0VJ4d > div:nth-child(1) > input:nth-child(1)')
# FAILS HERE
password_text_box.send_keys('fakepassword')
next_password_button = driver.find_element_by_css_selector('#passwordNext')
next_password_button.click()
Any suggestions?

I'm putting this here in case anyone comes across this problem themselves.
I couldn't resolve the logging in issue directly, but I found a workaround.
I had tried using cookies before but was doing something wrong, so instead, I just copied my Firefox profile (which has the auth cookie for google saved) and attached it to the webdriver.
ffp = FirefoxProfile(r"C:\Users\user\AppData\Roaming\Mozilla\Firefox\Profiles\sel_test")
driver = webdriver.Firefox(executable_path="D:\Selenium\geckodriver.exe", firefox_profile=ffp)

I had a similar issue, and did the following:
1) I first used the "find_element_by_css_selector" function, which selects the first occurence of the element with given attributes. This did not work.
2) Then I used the "find_elements_by_css_selector" (notice the s), which returns a list of the elements with given attributes. There was 2 elements in that list. Of course the first one (with index [0]) was not accessible by keyboard: this is equivalent of doing (1) above. But the second element (with index [1]) was accessible by keyboard.
Problem solved.

Related

Selenium driven browser shows different HTML code

I am not a very experienced coder so apologies if I say smth stupid.
I am using Python (in Spyder) to get Selenium to fill in a website form containing username and password. Here's the target - link.
When I lookup the "username" element by pressing F12 in a regular browser I get the following:
<input class="slds-input input" type="text" aria-describedby="" placeholder="Username" id="172:0" data-aura-rendered-by="176:0" data-interactive-lib-uid="2">
So I attempt to locate the element using the ID. However when I run the script, I get the following error in Chrome:
NoSuchElementException: no such element: Unable to locate element: {"method":"css selector","selector":"[id="172:0"]"}
Same when I run it in Firefox instead:
NoSuchElementException: Unable to locate element: [id="172:0"]
When I check HTML in the Selenium driven browser, I can see that the page code is (ie element ID) different, as below
<input class="slds-input input" type="text" aria-describedby="" placeholder="Username" id="78:2;a" data-aura-rendered-by="82:2;a" data-interactive-lib-uid="2">
My best guess is that the difference in HTML code is the reason for error. I found people posting similar issues but those were slightly different and I was not able to solve my issue using the solutions proposed there. I would appreciate is someone could help with my case.
Use xpath instead of id since it changes dynamically
Xpath for UserName: //label/following-sibling::input
Xpath for Password: //lightning-input//div//input
Sample working code which works in java convert with using above xpath in python and also add implicitlyWait and pageLoadTimeout befor launching the website
WebDriver driver = new ChromeDriver();
driver.manage().timeouts().pageLoadTimeout(10, TimeUnit.SECONDS);
driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
driver.get("https://lta-tennis.force.com/"); // WebElement
driver.findElement(By.xpath("//label/following-sibling::input")).sendKeys("dummy");
driver.findElement(By.xpath("//lightning-input//div//input")).sendKeys("dummy");
System.out.println(driver.getTitle());
Edit 1: Based on OP comment
This is working xpath
try these xpaths
//input[#placeholder="Username"]
//input[#placeholder="Password"]
here is the full code
from selenium import webdriver
import time
browser = webdriver.Chrome('C:\\driverpath\\chromedriver.exe')
url = 'https://lta-tennis.force.com/s/login/'
get = browser.get(url)
time.sleep(5)
browser.find_element_by_xpath('//input[#placeholder="Username"]').send_keys('hello')
browser.find_element_by_xpath('//input[#placeholder="Password"]').send_keys('pass')

How to write a Python script to search for a keyword in a particular website's database using the website's search bar?

I want to search for a keyword in a particular website using its search bar. For example I want to search about "birds" in Wikipedia. For that I have to open Google Chrome, then open Wikipedia, then search for the word "birds" in Wikipidea's search engine.
I want to automate this process using Python. I'm using PyCharm.
If emulating a browser user activity is OK to you, you may consider installing Selenium and Chrome webdriver (here is the instruction: https://pypi.org/project/selenium/ ).
"Example 1" is similar to the solution of your problem.
The search bar is <input type="search" name="search" placeholder="Search Wikipedia" title="Search Wikipedia [alt-shift-f]" accesskey="f" id="searchInput" tabindex="1" autocomplete="off"> element and has "searchInput" id, which you can use to select it with el = browser.find_element_by_id("searchInput")
Then use el.send_keys('birds' + Keys.RETURN) to fill the input with your request and search.
So the script may look like the following:
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
browser = webdriver.Chrome()
browser.get('https://en.wikipedia.org/wiki/Main_Page')
print("Enter a keyword to search on wikipedia: ", end='')
keyword = input()
elem = browser.find_element_by_id('searchInput') # Find the search box
elem.send_keys(keyword + Keys.RETURN)
# do something with the opened page
browser.quit()
If you don't want to emaluate browser activity, you may resolve it somehow with requests and BeautifulSoup4 modules, but the solution will be more complex, though, probably, more efficient

Python Selenium can't locate element

I have some troubles locating a username field on a webpage.
Using find_element_by_name/class prompts me with a 'no such element' error.
After a lot of fiddling, I still can not get this to work. Have not had this problem on any other webpages where I used the same method. Hope anyone can help me out!
<input type="text" class="_ph6vk _o716c" aria-describedby="" aria-label="Telefoonnummer, gebruikersnaam of e-mailadres" aria-required="true" autocapitalize="off" autocorrect="off" autocomplete="username" maxlength="30" name="username" placeholder="Telefoonnummer, gebruikersnaam of e-mailadres" value="">
The HTML above represents the element which I want to locate.
In case of slow page load/render, instruct the driver to wait for 5 seconds (for the element to load):
driver.implicitly_wait(5).
Explicitly getting the input:
driver.find_element_by_xpath("//input[contains(#class, '_ph6vk')]")
Though the class name looks to be dynamically generated on each particular page load, in that case, you will have to count inputs on the page before wanted one:
driver.find_element_by_xpath("//input[1]")
or write there a full absolute XPath.
Try the following:
driver.find_element_by_css_selector("input._ph6vk._o716c")
this won't work:
find_element_by_class("_ph6vk _o716c")
as they are two different classes.

Python3 (Selenium) can't locate password box

my current problem is that Python can't locate my password box.
<input class="stylepwd" name="pws" size="12" maxlength="12" onkeypress="return stEnter(event,this);" autocomplete="off" type="password">
Thats all i tried to do, but it always say it cant locate that box
element = driver.find_element_by_name('pws')
element = driver.find_element_by_class_tag('stylepwd')
element = driver.find_element_by_id('') #Yea, thats obviously not working ^^'
element.send_keys('mypassword')
Maybe there's another way I can type in that password. As soon as the site is loading, the cursor is in the box. Can I do anything with this? (Thats the site: http://imgur.com/a/6OIgm)
Python code: https://pastebin.com/3ydHwDkH
You can do something like this :
elem = driver.find_element_by_xpath('//input[#class="stylepwd"]')
This will give you the element input with class="stylepwd"
If it is in iframe, try
iframe = driver.find_elements_by_tag_name("iframe")[0]
driver.switch_to_frame(iframe)
then
element = driver.find_element_by_name('pws')

selenium python: how to send keys to a hidden password with differnet IDs

I'm currently using selenium with python 2.7 and I'm trying to to insert a password to the following form:
<tr id="mockpass">
<td>
<input type="text" value="something1" onfocus="document.getElementById('mockpass').style.display='none';
document.getElementById('realpass').style.display=''; document.getElementById('Irealpass').focus();">
</td>
</tr>
<tr id="realpass" style="display: none;">
<td>
<input type="password" name="Password" id="Irealpass" onblur="if(this.value=='') {document.getElementById('mockpass').style.display='';
document.getElementById('realpass').style.display='none';}">
</td>
</tr>
I tried using the following code but I keeping getting an error while trying to excute the clear command:
passBoxXpath='//*[#id="mockpass"]/td/input'
passBoxElement = WebDriverWait(driver, 10).until(lambda driver: driver.find_element_by_xpath(passBoxXpath))
passBoxElement.click()
passElement = WebDriverWait(driver, 10).until(lambda driver: driver.find_element_by_xpath('//*[#name="Password"]'))
passElement = driver.execute_script("arguments[0].style.display = 'block'; return arguments[0];",
passElement)
passElement.clear()
passElement.send_keys("myPassword")
The error:
raise exception_class(message, screen, stacktrace)
InvalidElementStateException: Message: Element is not currently interactable and may not be manipulated
I'm not sure if it's something to do with the focus or the blur that changes the element, but I get the element and fail to accsses it.
Thanks in advance!
update: the next line solved my case (still don't know why it didn't work):
driver.execute_script('document.getElementById("Irealpass").setAttribute("value","myPassword");')
In this way I didn't need to use the passBoxElement at all or changing the display style.
According to the docs http://selenium-python.readthedocs.io, this code should work.
elem = driver.find_element_by_css_selector("#mockpass input:first-child")
If you get the error anyway, scroll the browser window to element you are trying to access.
A couple things...
First off, if you are trying to perform user scenarios, you want to avoid using JavascriptExecutor (JSE). JSE allows you to do things on a page that an actual user cannot. Avoid using JSE unless you absolutely have to or if you don't care about user scenarios.
The problem is that the input that you want is hidden in the HTML you provided. You can see that in the 2nd TR, style="display: none;". If you look in the HTML of the first INPUT, you will see that the onfocus hides the first TR
onfocus="document.getElementById('mockpass').style.display='none';
and then unhides the 2nd TR
document.getElementById('realpass').style.display='';
So what you need to do is to focus the first INPUT which will expose the second INPUT.
One thing to note, from the JS in the second INPUT it looks like if you value is empty, it will rehide the second INPUT and expose the first (undoing what you just did).
onblur="if(this.value=='') {docum ...
I would do something like this
from selenium.webdriver.support import expected_conditions as EC
wait = WebDriverWait(driver, 10)
wait.until(EC.element_to_be_clickable(By.XPATH, '//*[#id="mockpass"]/td/input')).click()
wait.until(EC.element_to_be_clickable(By.XPATH, '//*[#id="Irealpass"]')).send_keys("myPassword")
Below should be work:
passwdEle = self.driver.find_element(by='id', value='Irealpass')
self.driver.execute_script('arguments[0].setAttribute("value","****")', passwdEle)

Categories

Resources