Python Selenium can't locate element - python

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.

Related

How do you change element attributes using Python?

I was wondering how to use python to change an element in a page's HTML code:
Specifically, from:
<input _ngcontent-mcp-c552="" type="number" name="bpm" placeholder="0" min="0" max="999" step="0.01" class="ng-valid ng-dirty ng-touched">
to
<input _ngcontent-mcp-c552="" type="number" name="bpm" placeholder="0" min="0" max="999" step="1" class="ng-valid ng-dirty ng-touched">
(Changing the step-size value)
The HTML I'm attempting to edit would not be of my own HTML file, but a public website. As such, the change would only be temporary; but I'm okay with that. Any help would be greatly appreciated. Thank you.
CONTEXT: Using automation, I'm trying to input a value (a number) into a textbox; but for some reason the send_keys function from selenium isn't sending any keys. So, I found that I could just select the element and hold the up arrow key until I attain the value I'd like. Problem is, the element's current step-size of 0.01 makes attaining the values I want (varying between 60-180) take very long. And now that's the problem I'm trying to sort out now.
To change the attribute from:
step="0.01"
to:
step="1"
you need to use setAttribute() as follows:
my_element = WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.XPATH, "//input[#class='ng-valid ng-dirty ng-touched' and #name='bpm'][#type='number']")))
driver.execute_script("arguments[0].setAttribute('step','1')", my_element)

Selenium element is not reachable by keyboard

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.

Web Scraping with Python: Iinput text and click a button

I was doing some web scraping with python (Linkedin site) and got stuck with the following 2 issues: 1) How do I input text on a search bar? 2) How to click a button? First, this is the search bar code:
<input aria-autocomplete="list" autocomplete="off" spellcheck="false"
placeholder="Búsqueda" autocorrect="off" autocapitalize="off" id="a11y-
ember6214" role="combobox" class="ember-text-field ember-view" aria-
expanded="false">
To input the text I was using the xpath (and it works) but it changes every time I login into the site:
search = driver.find_element_by_xpath('//*[#id="a11y-ember997"]')
search.send_keys('MedMake')
So could I use instead part of the input bar code above so that I can rerun my script multiple times?
My second point is 2) how to click a button. Again I was using the xpath but it changes after every login. My code was:
button = driver.find_element_by_xpath('//*[#id="nav-search-controls-wormhole"]/button')
button.click()
I inspected the button code and I would instead like to use data-vertical="PEOPLE" or any other of this unique fields (the tag button is not enough since there are many buttons on Linkedin site). By the way,how are all these inner fields called? I believe part of my problem arises from the lack of html code understanding.
<button data-vertical="PEOPLE" data-control-
name="vertical_nav_people_toggle" data-ember-action="" data-ember-
action-8620="8620" data-is-animating-click="true">
Gente
</button>
If id attribute values are dynamic you can use other attributes with static values:
search = driver.find_element_by_xpath('//input[#placeholder="Búsqueda"]')
search.send_keys('MedMake')
button = driver.find_element_by_xpath('//button[normalize-space()="Gente"]')
button.click()
First one use xpath
//input[contains(#class,'ember-text-field')]
Second one use the xpath
//button[#class='vertical_nav_people_toggle']

Setting the value of an <input> dropdown in Selenium with Python

I have a HTML page containing a form with an tag. I want to set the value of the drop down in this tag using Selenium.
This is how I retrieve the input element:
driver.find_element_by_xpath("/html/body/div[2]/div/div/form/div/div[1]/div[3]/div[1]/div/div[1]/input")
I tried to set the value using select_month.send_keys("09") but this is not accepted by the web page when I try to submit the form so I need to find another method.
EDIT: Here is the HTML of the form, I have ensured that it is the right element in my x-path:
<input autocomplete="off" tabindex="-1" class="ui-select-search ui-select-toggle ng-pristine ng-valid ng-touched" ng-click="$select.toggle($event)" placeholder="Select month" ng-model="$select.search" ng-hide="!$select.searchEnabled || ($select.selected && !$select.open)" ng-disabled="$select.disabled" type="text">
After messing around a bit and incorporating the better practice presented by alecxe, this solution worked...
driver.find_element_by_xpath("//input[#placeholder='Select month']").click()
driver.find_element_by_xpath("//*[contains(text(), '09')]").click()

Selenium to push button in form

Python: 3.4.1
Browser: Chrome
I'm trying to push a button which is located in a form using Selenium with Python. I'm fairly new to Selenium and HTML.
The HTML code is as follows:
<FORM id='QLf_437222' method='POST' action='xxxx'>
<script>document.write("<a href='javascript:void(0);' onclick='document.getElementById(\"QLf_437222\").submit();' title='xxx'>51530119</a>");</script>
<noscript><INPUT type='SUBMIT' value='51530119' title='xxx' name='xxxx'></noscript>
<INPUT type=hidden name="prodType" value="DDA"/>
<INPUT type=hidden name="BlitzToken" value="BlitzToken"/>
<INPUT type=hidden name="productInfo" value="40050951530119"/>
<INPUT type=hidden name="reDirectionURL" value="xxx"/>
</FORM>
I've been trying the following:
driver.execute("javascript:void(0)")
driver.find_element_by_xpath('//*[#id="QLf_437104"]/a').click()
driver.find_element_by_xpath('//*[#id="QLf_437104"]/a').submit()
driver.find_element_by_css_selector("#QLf_437104 > a").click()
driver.find_element_by_css_selector("#QLf_437104 > a").submit()
Python doesn't throw an exception, so it seems like I'm clicking something, but it doesn't do what I want.
In addition to this the webpage acts funny when the chrome driver is initialized from Selenium. When clicking the button in the initialized chrome driver, the webpage throws an error (888).
I'm not sure where to go from here. Might it be something with the hidden elements?
If I can provide additional information please let me know.
EDIT:
It looks like the form id changes sometimes.
What it sounds like you are trying to do, is to submit the form, right?
The <a> that you are pointing out is simply submitting that form. Since that is being injected via JavaScript, it's possible that it's not showing up when you try to click it. What i'd recommend, is doing:
driver.find_element_by_css_selector("form[id^='QLf']").submit()
That will avoid the button, and submit the appropriate form.
In the above CSS selector, i also used [id^= this means, find a <form> with an ID attribute that starts with QLf, because it looks like the numbers after, are automatically generated.

Categories

Resources