Python selenium select element by class - python

I tried to select an element with selenium but I'm a beginner.
Here is the element that I tried to select :
<button type="submit" class="btn btn-primary btn-block btn-form">
Connexion
</button>
I tried this lines on my script :
from selenium import webdriver
driver = webdriver.Chrome(executable_path="chromedriver.exe")
driver.get("https://skysand.fr")
connexion_button = driver.find_element_by_class_name("login")
connexion_button.click()
email_input = driver.find_element_by_id("email")
email_input.send_keys("XXXX")
password_input = driver.find_element_by_id("password")
password_input.send_keys("XXXX")
connect_button = driver.find_element_by_class_name("btn-primary btn-block btn-form")
connect_button.click()
But it is not working :(
selenium.common.exceptions.ElementClickInterceptedException: Message: element click intercepted: Element is not clickable at point (513, 955)
Thanks if you can help me !
(sorry for my bad English...)

In order to select element by multiple class names you should use css_selector or XPath. Also, for this element it would better to use this css locator:
button[type='submit']
So try this:
connect_button = driver.find_element_by_css_selectro("button[type='submit']")
connect_button.click()
Also, this your code needs waits. With them it will look like this:
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
wait = WebDriverWait(driver, 20)
driver = webdriver.Chrome(executable_path="chromedriver.exe")
driver.maximize_window()
driver.get("https://skysand.fr")
wait.until(EC.visibility_of_element_located((By.CSS_SELECTOR, ".login"))).click()
wait.until(EC.visibility_of_element_located((By.CSS_SELECTOR, "#email"))).send_keys("XXXX")
wait.until(EC.visibility_of_element_located((By.CSS_SELECTOR, "#password"))).send_keys("XXXX")
wait.until(EC.visibility_of_element_located((By.CSS_SELECTOR, "button[type='submit']"))).click()

Related

How to identify the object with in the HTML using Selenium and Python

Might be a bit of an edge use case, but I need to identify and then click on an object on a login page. The page itself is dynamically generated and all of the (4) buttons are labeled as such:
button class="MuiButtonBase-root MuiButton-root MuiButton-text jss100" tabindex="0" type="button">
With the full breakdown of the button I'm trying to click being:
<button class="MuiButtonBase-root MuiButton-root MuiButton-text jss100" tabindex="0" type="button"><span class="MuiButton-label"><div class="MuiBox-root jss129 jss101 jss128" params="[object Object]"><div class="MuiBox-root jss131 jss104 jss130"><svg class="MuiSvgIcon-root" focusable="false" viewBox="0 0 24 24" aria-hidden="true"><path d="M21 6h-2v9H6v2c0 .55.45 1 1 1h11l4 4V7c0-.55-.45-1-1-1zm-4 6V3c0-.55-.45-1-1-1H3c-.55 0-1 .45-1 1v14l4-4h10c.55 0 1-.45 1-1z"></path></svg></div><div class="MuiBox-root jss133 jss107 jss132">Q&A</div></div><div class="MuiBox-root jss135 jss107 jss134">Security Questions</div></span><span class="MuiTouchRipple-root"></span></button>
I've tried mapping the XPATH, using CSS Selectors, trying to find the strings of text embedded in in the button, and even trying to find the SVG by using the following:
driver.find_element(by=By.XPATH , value = '//path[#d="
Any ideas how I can get Selenium to identify this object without any static identifiers?
Here's everything I've got so far:
#I know most of these are extraneous references :/
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support.expected_conditions import presence_of_element_located
from selenium.webdriver.support import expected_conditions as EC
import time
import sys
url = 'https://***.com'
chrome_driver_path = '/Users/***/chromedriver'
chrome_options = Options()
chrome_options.add_argument('--headless')
webdriver = webdriver.Chrome(
executable_path=chrome_driver_path, options=chrome_options
)
with webdriver as driver:
wait = WebDriverWait(driver, 10)
driver.get(url)
wait.until(presence_of_element_located((By.ID, "password")))
inputUsername = driver.find_element_by_id("loginID")
inputPassword = driver.find_element_by_id("password")
findLoginButton = driver.find_element_by_id("submit-button")
inputUsername.send_keys('[username]')
inputPassword.send_keys('[password]')
findLoginButton.click()
# element1 = driver.find_element_by_css_selector("div.MuiBox-root.jss135.jss107.jss134")
# wait.until(presence_of_element_located(element1))
# element1.click()
driver.find_element(by=By.XPATH , value = '//path[#d="M21 6h-2v9H6v2c0 .55.45 1 1 1h11l4 4V7c0-.55-.45-1-1-1zm-4 6V3c0-.55-.45-1-1-1H3c-.55 0-1 .45-1 1v14l4-4h10c.55 0 1-.45 1-1z"]')
#CSS_SELECTOR,value="#root > div > div > ^MuiBox-root^ > ^MuiBox-root^ > form > div > div.MuiCollapse-container.MuiCollapse-entered > div > div > div > button:nth-child(5)]")
#find_element_by_xpath("/html/body/div/div/div/div[2]/div[2]/form/div/div[1]/div/div/div/button[4]").click()
driver.close()
To click on the element you need to induce WebDriverWait for the element_to_be_clickable() and you can use either of the following locator strategies:
Using XPATH and the innerText Security Questions:
WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.XPATH, "//button[contains(#class, 'MuiButtonBase-root')]/span[#class='MuiButton-label']//div[text()='Security Questions']"))).click()
Using XPATH and the innerText Q&A:
WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.XPATH, "//button[contains(#class, 'MuiButtonBase-root')]/span[#class='MuiButton-label']//div[text()='Q&A']"))).click()
Note: You have to add the following imports :
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
I think your problem is that your locator is wrong, which is why your element isn't being found.
Try this:
driver.find_element(by=By.XPATH, "//button[contains(.//div, 'Security Questions')]")
This Xpath will return a button element that contains a div with the text "Security Questions."

I'm trying to use the <button class= instead of using the whole XPATH as the id: changes on each product

from selenium import webdriver
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
from selenium.webdriver.common.keys import Keys
from selenium.webdriver import ActionChains
PATH = "C:\Program Files (x86)\chromedriver.exe"
driver = webdriver.Chrome(PATH)
driver.maximize_window()
driver.get("https://accounts.ebuyer.com/customer/account/index.html?action=bG9naW4=")
title = driver.find_element_by_name("email")
title.clear()
title.send_keys("johnsmith#gmail.com")
password = driver.find_element_by_id("password")
password.send_keys("pass123")
driver.find_element_by_xpath('//*[#id="login"]/div[4]/input').click()
driver.find_element_by_xpath('/html/body/div[3]/div/button[2]').click()
#accepts cookies
driver.get("https://www.ebuyer.com/search?q=graphics+cards")
WebDriverWait(driver, 10)
try:
element = WebDriverWait(driver, 5).until(
EC.presence_of_element_located((By.XPATH,'//*[#id="grid-view"]/div[1]/div[4]/button'))
) #finds add to basket button
element.click()
driver.find_element_by_xpath('/html/body/header/div/div[3]/div/a[1]').click()
print("IN BASKET")
#adds to basket if found
except:
element = WebDriverWait(driver, 5).until(
EC.presence_of_element_located((By.XPATH,'//*[#id="main-
content"]/div/div[1]/div[2]/div[2]/div/div[2]/ul/li[2]/a'))
)
element.click()
#moves to next page
this is what I'm trying to click but the id changes on each product grid.
<button class="button button--mini-basket button--small js-add-to-mini-basket" data-product-
id="798879" data-ajax-basket-url="https://orders.ebuyer.com/customer/products/index.html?
action=YWpheF9jYXJ0X2FkZF9pdGVt" data-analytics-event="click" data-event-category="Search Listings - Grid" data-event-action="Product Click" data-event-label="Add to Basket Button">Add to
Basket</button>
I want to take <button class="button button--mini-basket button--small js-add-to-mini-basket" and
use this instead of By.XPATH,'//*[#id="grid-view"]/div[1]/div[4]/button'
I'm trying to scan the full page to find the Add to Basket Button and if it can't find that then it
will move on to the next page and repeat until it is found.
I have just built my first pc and I cannot get a graphics card anywhere so I want to use this grab
one.
I've recently found a love for coding so I'm quite new to this, I hope I've explained myself properly
and any help would be appreciated.
Use following xpath to identify. Use element_to_be_clickable() instead presence_of_element_located()
element =WebDriverWait(driver, 5).until(EC.element_to_be_clickable((By.XPATH,"//button[text()='Add to Basket']"))
Try following xpath
//button[#class='button button--mini-basket button--small js-add-to-mini-basket' and contains(text(),'Add to Basket')]

How to submit an angular form with selenium python after filling out

<button ng-click="LoginForm.login($event)" id="login_btn" ng-disabled="LoginForm.isSubmitting" type="submit" class="btn btn-info btn-large btn-submit ModalLoginSignup-loginForm-submitBtn" fl-analytics="NormalLogin" i18n-id="3bbbad631029e3575da7a151bba4f37c" i18n-msg="Log In">
Log In
</button>
this is what I am trying.
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
driver = webdriver.Firefox()
driver.implicitly_wait(5)
driver.maximize_window()
driver.get("https://xxxxxxxxx.com")
user = driver.find_element_by_name("username")
password = driver.find_element_by_name("password")
user.clear()
user.send_keys("xxxxxxxx")
password.clear()
password.send_keys("xxxxxxx")
driver.implicitly_wait(5)
# password.send_keys(u'\ue007')
# driver.click()
# driver.implicitly_wait(30)
# driver.find_element_by_id("login_btn").send_keys(u'\ue007')
# driver.find_element_by_id('login_btn').send_keys(Keys.ENTER)
# login_button = driver.find_element_by_xpath("")
driver.find_element_by_xpath("//[#id='login_btn']").send_keys(u'\ue007')
# login_button.submit()
# driver.find_element_by_css_selector(".ModalLoginSignup-loginForm-submitBtn").submit()
As per the HTML you have shared the desired element is an Angular element so to invoke click() on the element you have to induce WebDriverWait for the element to be clickable and you can use either of the following solutions:
CSS_SELECTOR:
WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.CSS_SELECTOR, "button.btn-submit.ModalLoginSignup-loginForm-submitBtn#login_btn"))).click()
XPATH:
WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.XPATH, "//button[#class='btn btn-info btn-large btn-submit ModalLoginSignup-loginForm-submitBtn' and #id='login_btn']"))).click()
Note : You have to add the following imports :
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC

Selenium Python get_element by ID failing

Can someone help me understand why my code fails to find the element by ID. Code below:
from selenium import webdriver
driver=webdriver.Firefox()
driver.get('https://app.waitwhile.com/checkin/lltest3/user')
element = driver.find_element_by_id("guestPhone")
Inspecting element shows the ID clearly.
<input type="tel" name="guestPhone" id="guestPhone" class="form-control ng-pristine ng-empty ng-invalid ng-invalid-phone-validator ng-invalid-required ng-touched" ng-model="form.model" ng-model-options="{ 'updateOn': 'default blur', 'debounce': { 'default': 350, 'blur': 0 } }" uib-typeahead="guest.phone for guest in form.onChange({value:$viewValue})" typeahead-min-length="6" typeahead-on-select="form.onSelect({guest:$item})" typeahead-select-on-exact="true" uib-tooltip="Please enter valid number. Include country code for non-US numbers" tooltip-trigger="'none'" tooltip-is-open="(form.guestForm.$submitted || form.guestForm.guestPhone.$touched) && form.guestForm.guestPhone.$invalid" tooltip-placement="bottom" ng-required="::form.required" phone-validator="US" placeholder="Mobile phone" title="Please enter a valid phone number" autocomplete="nope" next-on-enter="" aria-autocomplete="list" aria-expanded="false" aria-owns="typeahead-47-2884" required="required" style="">
P.S. I've also tried XPath and name as well. Still no luck.
You need to wait for the element to become visible on the page. You can tell this is loaded in dynamically because if you right-click on the page in chrome and view source you'll see there's no guestPhone element. It gets loaded in with javascript
Here's an example from http://isaacviel.name/make-web-driver-wait-element-become-visiable/:
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
driver = webdriver.Firefox()
driver.get("http://somedomain/url_that_delays_loading")
try:
element = WebDriverWait(driver, 10).until(
EC.visibility_of_element_located((By.ID, "myDynamicElement"))
)
finally:
driver.quit()
You can try with web driver wait :
Code :
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
driver = webdriver.Chrome(executable_path = r'D:/Automation/chromedriver.exe')
driver.maximize_window()
driver.get("https://app.waitwhile.com/checkin/lltest3/user")
wait = WebDriverWait(driver, 10)
element = wait.until(EC.element_to_be_clickable((By.ID, 'guestPhone')))
element.send_keys('006867987')

Button"+" is not being clicked in selenium

Source code:
<input type="button" value="+" id="hour_add" class="ui-button ui-widget ui-state-default ui-corner-all" role="button" aria-disabled="false">
My code:
driver.find_element_by_xpath("//input[contains(#id, 'hour_add')]").click();
This button is not clicked.
There could be multiple reasons for the problem and there is certainly not enough information to answer, but here are the possible reasons:
there are multiple elements matching the XPath expression and a wrong element is clicked
you might need to move to the element and click:
from selenium.webdriver.common.action_chains import ActionChains
ActionChains(driver).move_to_element(element).click(element).perform()
you might need to scroll into view of the element:
driver.execute_script("arguments[0].scrollIntoView();", element)
you might need to click via javascript:
driver.execute_script("arguments[0].click();", element)
you might need to wait for element to be clickable:
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
element = WebDriverWait(driver, 10).until(
EC.element_to_be_clickable((By.ID, "hour_add"))
)
element.click()
sometimes even maximizing the browser window can help:
driver.maximize_window()
When you have Id available for the element you want to click on, then just use find_element_by_id.
driver.find_element_by_id('hour_add').click()

Categories

Resources