I'm using Selenium with Python3 to automate entering data into a website.
I have tried looking everywhere for how to deal with selecting an element by class if there is more than one but I can't figure out how to select the accordion-toggle[1]. Nothing happens on selenium but it works fine on any browser. Also, is there any way to just use the regular javascript or jquery commands?:
accordion=find_element_by_class("accordion-toggle"[1])
accordion.click()
#otheraccordion=find_element_by_css_selector("#AdvancedAddress > div.accordion-heading.in > div.accordion-toggle > span.accordionExpandCollapse")
#otheraccordion.click()
StreetNameField=driver.find_element_by_id("Advanced_FindMyParcel_PropertyStreetName")
StreetNameField.send_keys("Sherman")
ZipField=driver.find_element_by_id("Advanced_FindMyParcel_PropertyZip")
ZipField.send_keys("90201")
ZipButton=driver.find_element_by_id("btnSearchFindMyParcels")
ZipButton.click()
You actually can use document.getElementsByClassName() through execute_script() call:
driver.execute_script("document.getElementsByClassName('accordion-toggle')[0].click();")
But I would not go down to executing javascript for such a simple task. Easier to locate the element using find_element_by_class_name():
accordion = driver.find_element_by_class_name('accordion-toggle')
accordion.click()
You are looking for find_element(s)_by_css_selector - reference here - use the css prefix '.classname` to indicate the class.
e.g. to find
<div class='theClass'>
driver.find_elements_by_css_selector('.theClass')
You can also use the By syntax:
driver.find_elements(By.CSS_SELECTOR, '.theClass')
Edit
It seems the problem may be more to Clicking the element, rather than finding it.
Ensure the element is visible
For Chrome, you may need to mimic hovering the mouse over the element before clicking this - see Actions / ActionChains MoveToElement to hover over the element.
For IE, you may need to ensure the browser / frame gets the focus, prior to the element Click - you may need to apply a hack like one of these.
In addition to #alecxe response, I would also suggest using the function find_elements_by_class_name instead of find_element_by_class_name in case there are multiple elements with the same class name.
accordion = driver.find_elements_by_class_name('accordion-toggle')[1] # Selects second element
accordion.click()
Using find_element_by_class_name will return only the first element with that class name.
Related
My goal is to get an element within a dropdown menu that needs to be clicked in order to appear using python selenium. Also, it seems that before the click, hovering is necessary.
I tried to click the dropdown menu like this:
element = wait().until(EC.presence_of_element_located((By.CLASS_NAME, "c-topmenu c-topmenu--create c-topmenu--userbar tw-inline-flex")))
element.click()
def wait():
return WebDriverWait(driver, 30)
And tried to use hovering:
Hover = ActionChains(driver).move_to_element(element)
Hover.click().build().perform()
Still, I get a TimeoutException and can't figure out a solution.
The website komoot looks like this before clicking the dropdown menu:
The website komoot looks like this after expanding it:
Ok here is how i was able to get this working.
after the login i grapped the wrapper element from the link with:
more_menu_wrapper = driver.find_element_by_css_selector("div[data-test-id='more_menu']")
after that i could click the desired element with:
more_menu_wrapper.find_element_by_tag_name("a").click()
You are using a wrong locator.
In case of multiple class names you should use css_selector or XPath, not by class name.
Also, here you have an unique attribute of data-test-id, you should use it.
Also, you should wait for element visibility or clickability, not just for element presence.
So your code could be:
element = wait().until(EC.visibility_of_element_located((By.CSS_SELECTOR, "div[data-test-id='more_menu']")))
I have tried to make my script click the log in button on the Spotify login page. I have been searching all day for a solution, but no matter what class, css or whatever I put in, it is just saying it could not find the object.
My code:
import selenium
from selenium import webdriver
browser = webdriver.Firefox()
browser.get("https://accounts.spotify.com/en/login?
continue=https:%2F%2Fwww.spotify.com%2Fdk%2Faccount%2Foverview%2F")
username = browser.find_element_by_id("login-username")
password = browser.find_element_by_id("login-password")
username.send_keys("myUser")
password.send_keys("myPass")
login = browser.find_element_by_class_name('ng-pristine ng-valid-sp-
disallow-chars ng-invalid ng-invalid-required').click()
It is the last line I have a problem with. Note: This is just one of the options I tried.
You can try this code that have xpath:
login = browser.find_element_by_xpath("//button[contains(.,'Log In')]");
login.click();
You're using multiple classes in your class selector. Try using only one class. Something like this:
browser.find_element_by_class_name('btn-green').click()
If it still doesn't work, perhaps the element has not yet been rendered when you try to click it, so you may want to try with an explicit wait
Also, I checked out your selector and it looks like you weren't even pointing to the button, but to the form.
And finally, a class selector may not be the optimal way to locate your element here. I'd probably go with a XPath selector to find the button that contains the text Log In, using the following XPath
//button[text()='Log In']
Use this, i Updated the answer:
login = browser.find_element_by_xapth("//button[#class='btn btn-sm btn-block btn-green ng-binding']")
login .click()
browser.find_element_by_xpath(".//button[contains(text(), 'Log In'])").click()
This should work so give it a try. :)
As #Verv stated, you could be having timing issues. So just for the test try with time.sleep() to see if this is it.
I am working with selenium (python) and I would like for it to click on a button. The code goes something like this:
from selenium import webdriver
driver = webdriver.Firefox()
driver.get('my_url')
try:
driver.find_element_by_partial_link_text('Mais').click()
except:
pass
Nothing at all happens. After inspecting the source, and I am pretty sure this is the element I want to find:
<input class="ksb _kvc" value="Mais resultados" id="smb" data-lt="Carregando..." jsaction="str.smr" data-ved="0ahUKEwjPtK6Fwv3PAhVGI5AKHTkSDVsQxdoBCE8" type="button" />
Have you tried
driver.find_element_by_id('smb').click()
Rather than
driver.find_element_by_partial_link_text('Mais').click()
I suspect nothing happens because an exception is thrown in your original code if the find fails.
When attempting to locate elements I would usually use id/name as these are normally unique. For a full list see selenium-python.readthedocs.io/locating-elements.html
You are having issue clicking the button because you are using driver.find_element_by_partial_link_text() which is only good for finding link (anchor elements) by its partial text, and performing actions on it.
You should rely on the other find_element_by_xxxx() methods which allow us to find by element ID, Name, XPath, CSS selector, or Class name.
Refer the documentation on locating elements at : http://selenium-python.readthedocs.io/locating-elements.html
So, using WebDriver python binding, I came across a problem that I need to wait until an element is refreshed on the page. Say, I have two radio buttons, and by clicking either of them, a label text is changed.
Currently, if I click on one and get the text and then click on the other and get the text again, I will get the same text although it has changed. Thus, I think I need to wait for the element to be refreshed.
On Java documentation, there is a refreshed expected condition which appears to be useful in this case. But I'm unable to find the python version of it. What is its equivalent? How can I workaround this?
text_to_be_present_in_element() under expected_conditions.py is similar to what you're looking for. If it's not the value that's changing but instead another field like textContent, you could roll a custom solution which is similar to text_to_be_present_in_element().
def attribute_text_is_in_element(text, locator, attribute):
try:
element_text = driver.find_element(locator).get_attribute(attribute)
if text == element_text:
return True
else:
return False
except StaleElementReferenceException:
return False
Using the Python version of Selenium, is it possible to click some element in the DOM and to specify the coordinates where you want to click it?
The Java version has the method clickAt, which actually does exactly what I am looking for, but can't find the equivalent in Python.
This should do it! Namely you need to use action chains from webdriver. Once you have an instance of that, you simply register a bunch of actions and then call perform() to perform them.
from selenium import webdriver
driver = webdriver.Firefox()
driver.get("http://www.google.com")
el=driver.find_elements_by_xpath("//button[contains(string(), 'Lucky')]")[0]
action = webdriver.common.action_chains.ActionChains(driver)
action.move_to_element_with_offset(el, 5, 5)
action.click()
action.perform()
This will move the mouse 5 pixels down and 5 pixels right from the upper-left corner of the button I feel lucky. Then it will click().
Notice that you must use perform(). Else nothing will happen.
The reason you are getting confused is clickAt is an old v1 (Selenium RC) method.
WebDriver has a slightly different concept, of 'Actions'.
Specifically, the 'Actions' builder for the Python bindings live here.
The idea of the clickAt command is to click at a certain position relative to a particular element.
The same is achievable within the WebDriver, using the 'Actions' builder.
Hopefully this updated documentation can help.
You can perform the task with the Action chains in the python specially with Edge browser:
from selenium.webdriver import ActionChains
actionChains = ActionChains(driver)
button_xpath = '//xapth...'
button = driver.find_element_by_xpath(button_xpath)
actionChains.move_to_element(button).click().perform()
But sometimes Action chain does not finds the DOM element. Hence better option to use execute scipt in following way:
button_xpath = '//xapth...'
button = driver.find_element_by_xpath(button_xpath)
driver.execute_script("arguments[0].click();", button)
I've not personally used this method, but looking through the source code of selenium.py I've found the following methods that look like they'd do what you want - They look to wrap clickAt:
def click_at(self,locator,coordString):
"""
Clicks on a link, button, checkbox or radio button. If the click action
causes a new page to load (like a link usually does), call
waitForPageToLoad.
'locator' is an element locator
'coordString' is specifies the x,y position (i.e. - 10,20) of the mouse event relative to the element returned by the locator.
"""
self.do_command("clickAt", [locator,coordString,])
def double_click_at(self,locator,coordString):
"""
Doubleclicks on a link, button, checkbox or radio button. If the action
causes a new page to load (like a link usually does), call
waitForPageToLoad.
'locator' is an element locator
'coordString' is specifies the x,y position (i.e. - 10,20) of the mouse event relative to the element returned by the locator.
"""
self.do_command("doubleClickAt", [locator,coordString,])
They appear in the selenium object and here is their online API documentation.