Selecting button in Selenium python using web driver - python

Can anyone please let me know how to correctly click on the button using Selenium webdriver?
I have the following html element I want to click:
<button type="button" class="btn button_primary" data-bind="click: $parent.handleSsoLogin.bind($parent)"> Sign In
</button>
I am trying to use WebDriver with python but it doesn't find the element. Please advise how to address it?
from xml.dom.expatbuilder import InternalSubsetExtractor
from selenium.webdriver.common.by import By
import time
# imports parts of interest
from selenium import webdriver
# controlling the chrome browser
driver = webdriver.Chrome()
link=xxxxx
driver.get(link2)
# login = driver.find_element(By.LINK_TEXT,"Login")
time.sleep(10)
# login.click()
driver.find_element(By.ID,'CybotCookiebotDialogBodyLevelButtonLevelOptinAllowAll')
time.sleep(10)
login=driver.find_element(By.CSS_SELECTOR("<button type="buttonclass="btn button_primary" data-bind="click: $parent.handleSsoLogin.bind($parent)"> Sign In
So far tried different elements but it doesn't find it

Here is a complete example of how you can go to login page and login, on terex parts (why you edited out the url, I don't know).
Assuming you have a working Selenium setup, you will also need the following imports:
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
import time as t
[...]
wait = WebDriverWait(driver, 5)
url = 'https://parts.terex.com/'
driver.get(url)
t.sleep(3)
try:
wait.until(EC.element_to_be_clickable((By.ID, "CybotCookiebotDialogBodyLevelButtonLevelOptinAllowAll"))).click()
print('accepted cookies')
except Exception as e:
print('no cookie button!')
t.sleep(4)
login_button = wait.until(EC.element_to_be_clickable((By.XPATH, '//button[#data-bind="click: $parent.handleSsoLogin.bind($parent)"]')))
login_button.click()
print('clicked login button')
t.sleep(5)
wait.until(EC.frame_to_be_available_and_switch_to_it((By.XPATH, '//iframe[#class="truste_popframe"]')))
try:
wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR, "a[class='call']"))).click()
print('accepted cookies again')
except Exception as e:
print('no cookie iframe and button!')
driver.switch_to.default_content()
user_email_field = wait.until(EC.element_to_be_clickable((By.XPATH, '//input[#id="idcs-signin-basic-signin-form-username"]')))
user_email_field.send_keys('parts_dealer_112')
password_field = wait.until(EC.element_to_be_clickable((By.XPATH, '//input[#placeholder="Password"]')))
password_field.send_keys('password112')
login_button = wait.until(EC.element_to_be_clickable((By.XPATH, '//oj-button[#id="idcs-signin-basic-signin-form-submit"]')))
login_button.click()
print('logged in unsuccessfully')
Selenium documentation can be found here: https://www.selenium.dev/documentation/

I have managed to locate the element using Chrome Plugin Selectors Hub
Selectors Hub Google Chrome. It allows quickly select Xpath for elements which then can be used with Xpath locator- makes life so much easier- highly recommend giving it a try if you are struggling.
login=driver.find_element(By.XPATH,"//button[#data-bind='click: $parent.handleSsoLogin.bind($parent)']").click()

Related

Selenium ElementNotInterectable

Hello there I try to scrape this website - https://dom.ria.com/uk/realtors/ and I get a popup message below about cookies when I press accept it dismiss and I can access phone numbers but When I try to press this button using selenium I get erro ElementNotInterectable.
Here is my code to handle it:
cookies = driver.find_element(By.XPATH, "//label[#class='button large']")
driver.implicitly_wait(20)
cookies.click()
I tried to use driver.implicitly_wait() but it still doesn't work.
How can I fix this?
Your xpath matches two elements on the page. In this case, selenium simply grabs the first element, which does not happen to be the one that you want. Try something like this:
cookies = driver.find_elements(By.XPATH, "//label[#class='button large']")
# wait if you have to
cookies[1].click()
A reliable way of accepting cookies on that page would be:
from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
### other imports, setting up selenium, etc ##
browser = webdriver.Chrome(service=webdriver_service, options=chrome_options)
wait = WebDriverWait(browser, 20)
url = 'https://dom.ria.com/uk/realtors/'
browser.get(url)
try:
wait.until(EC.element_to_be_clickable((By.XPATH, '//div[#class="nowrap gdpr_settings_not_checked"]/label'))).click()
print('accepted cookies')
except Exception as e:
print('no cookie button!')
Selenium docs can be found at https://www.selenium.dev/documentation/

How to accept cookies popup within #shadow-root (open) using Selenium Python

I am trying to press the accept button in a cookies popup in the website https://www.immobilienscout24.de/
Snapshot:
I understand that this requires
driver.execute_script("""return document.querySelector('#usercentrics-root')""")
But I can't trickle down the path to the accept button in order to click it. Can anyone provide some help?
This is one way (tested & working) you can click that button: please observe the imports, as well as the code after defining the browser/driver:
from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.action_chains import ActionChains
chrome_options = Options()
chrome_options.add_argument("--no-sandbox")
chrome_options.add_argument('disable-notifications')
import time as t
webdriver_service = Service("chromedriver/chromedriver") ## path to where you saved chromedriver binary
browser = webdriver.Chrome(service=webdriver_service, options=chrome_options)
actions = ActionChains(browser)
url = 'https://www.immobilienscout24.at/regional/wien/wien/wohnung-kaufen'
browser.get(url)
page_title = WebDriverWait(browser, 3).until(EC.presence_of_element_located((By.CSS_SELECTOR, "a[title='Zur Homepage']")))
actions.move_to_element(page_title).perform()
parent_div = WebDriverWait(browser, 20000).until(EC.presence_of_element_located((By.ID, "usercentrics-root")))
shadowRoot = browser.execute_script("return arguments[0].shadowRoot", parent_div)
try:
button = WebDriverWait(shadowRoot, 20).until(EC.element_to_be_clickable((By.CSS_SELECTOR, "button[data-testid='uc-accept-all-button']")))
button.click()
print('clicked')
except Exception as e:
print(e)
print('no click button')
That page is reacting to user's behavior, and it will only fully load the page once it detects mouse movements, hence the ActionChains() part of the code. After that, we drill down into the shadow root element, we locate the button (using Waits, to make sure it's clickable), and then we click it.
Selenium documentation can be found at https://www.selenium.dev/documentation/
The element Alle akzeptieren within the website is located within a #shadow-root (open).
Solution
To click on the element Alle akzeptieren you have to use shadowRoot.querySelector() and you can use the following Locator Strategy:
Code Block:
driver.execute("get", {'url': 'https://www.immobilienscout24.de/'})
time.sleep(10)
item = driver.execute_script('''return document.querySelector('div#usercentrics-root').shadowRoot.querySelector('button[data-testid="uc-accept-all-button"]')''')
item.click()

How do I force Selenium Python to click on the correct button?

I'm very new to Selenium and am trying to build a scraper on this site that clicks on the "16. token URI" button, enters a number into the input field, and clicks the the Query button. But no matter how I define the element to be clicked, Selenium clicks on a different button, even thought I've copied the XPATH exactly. Obviously I can't move onto the next two steps until I solve this one. How do I force Selenium to scroll down to the 16th button and click it?
from selenium import webdriver
from webdriver_manager.chrome import ChromeDriverManager
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.action_chains import ActionChains
from selenium.webdriver.common.keys import Keys
from selenium.common.exceptions import TimeoutException
import time
service = Service(executable_path=ChromeDriverManager().install())
driver = webdriver.Chrome(service=service)
driver.maximize_window()
driver.get("https://etherscan.io/address/0xd0318da435dbce0b347cc6faa330b5a9889e3585#readContract")
assert "ASMBrain" in driver.title
try:
delay = 5
WebDriverWait(driver, delay).until(EC.frame_to_be_available_and_switch_to_it((By.ID, "readcontractiframe")))
element = driver.find_element(By.XPATH, "//*[#id='readHeading16']/a")
# ActionChains(driver).move_to_element(element).click().perform()
driver.execute_script("arguments[0].scrollIntoView(true);", element)
WebDriverWait(driver, delay).until(EC.visibility_of((element))).click()
# driver.find_element(By.XPATH, "//input[#id='input_16_1']").send_keys('10')
# driver.find_element(By.XPATH, "//button[#id='btn_16']").click()
time.sleep(30)
driver.quit()
print("Page is ready!")
except TimeoutException:
print("Loading took too much time!")
I suggest using a different xpath. Try using the href of the a tag.
time.sleep(5)
element = WebDriverWait(driver, 10).until(EC.visibility_of_element_located((By.XPATH, "//a[contains(text(), '16. tokenURI')]")))
element.click()
Message: element click intercepted: Element <iframe width="100%" id="readcontractiframe" src="/readContract?m=normal&a=0xd0318da435dbce0b347cc6faa330b5a9889e3585&v=0xd0318da435dbce0b347cc6faa330b5a9889e3585" frameborder="0" scrolling="no" style="height: 1019px; padding: 0px 0.5px;" cd_frame_id_="5f818ce91d8292c77481277348168d1d"></iframe> is not clickable at point (674, 633). Other element would receive the click: <div class="alert alert-light border shadow p-3" role="alert">...</div>
(Session info: chrome=96.0.4664.110)
You had an element click interception deal with the popup first. Then proceed to click it as well.
wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR,"#btnCookie"))).click()
try:
wait.until(EC.frame_to_be_available_and_switch_to_it((By.ID, "readcontractiframe")))
elem=wait.until(EC.element_to_be_clickable((By.XPATH,"//a[contains(.,'tokenURI')]")))
elem.click()
print("Page is ready!")
except Exception as e:
print(str(e))
print("Loading took too much time!")

Confirm if link is disabled selenium/Python

The below code finds the correct link from an unordered list in a browser, however the EC.element_to_be_clickable function doesn't work because if the link wasn't clickable, it will require the browser to be refreshed (to check again).
Instead, is there any way for the link to be checked if it is disabled (and click() if it isn't? The link will come in one of the below formats
<a class="Button disabled">Purchase</a>
<a class="Button">Purchase</a>
Code below
from selenium import webdriver
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
try:
if len(driver.find_elements(By.XPATH, "//span[text()='$30.00']/../following-sibling::div/a[text()='Purchase']")) > 0:
print("Found, now attempting to click link")
WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.XPATH, "//span[text()='$30.00']/../following-sibling::div/a[text()='Purchase']"))).click()
To check if a link is disabled, ie. if its class contains 'disabled', just look for it in its class:
try:
if len(driver.find_elements(By.XPATH, "//span[text()='$30.00']/../following-sibling::div/a[text()='Purchase']")) > 0:
elem = driver.find_element(By.XPATH, "//span[text()='$30.00']/../following-sibling::div/a[text()='Purchase']")
print("Found, now attempting to click link")
if "disabled" in elem.get_attribute("class"):
print("Link disabled! Refreshing page.")
driver.refresh()
else:
elem.click()

How to execute all javascript content on webpage with selenium to find and send login form info on fully loaded webpage

I've been trying to make a Python script to login into a certain website, navigate through the menu, fill out a form and save the file it generates to a folder.
I've been using Selenium trying to make the website fully load so i can find the elements for the login, but i'm being unsucessful, maybe because the website does a lot of JavaScript content before it fully loads, but i can't make it fully load and show me the data i want.
I tried Robobrowser, Selenium, Requests and BeautifulSoup to get it done.
import requests
from bs4 import BeautifulSoup
from selenium import webdriver
url = "https://directa.natal.rn.gov.br/"
driver = webdriver.Chrome(executable_path="C:\\webdrivers\\chromedriver.exe")
driver.get(url)
html = driver.execute_script("return document.documentElement.outerHTML")
sel_soup = BeautifulSoup(html, 'html.parser')
senha = driver.find_element_by_xpath('//*[#id="senha"]')
senha.send_keys("123")
I expected to have filled the password (senha) field with "123" but i can't even find the element.
It seems like what's needed here is a little bit of a scroll, wait and switch, incase the login fields just aren't ready for input :) The below should work, whereby we actually scroll to the element, having switch to the iframe, before we interact with the rest of the login form. You're able to adjust the delay from 5 seconds to anything of your preference.
from selenium import webdriver
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.common.exceptions import TimeoutException
""" Variables """
url = "https://directa.natal.rn.gov.br/"
delay = 5 # seconds
""" Initiate driver """
driver = webdriver.Chrome(executable_path="C:\\webdrivers\\chromedriver.exe")
""" Go to url """
driver.get(url)
""" Iframe switch """
WebDriverWait(driver, 10).until(EC.frame_to_be_available_and_switch_to_it((By.CSS_SELECTOR,"frame[name='mainsystem'][src^='main']")))
""" Attempt to get all our elements """
try:
""" Username """
usuario = WebDriverWait(driver, delay).until(EC.presence_of_element_located((By.ID, 'usuario')))
""" Password """
senha = WebDriverWait(driver, delay).until(EC.presence_of_element_located((By.ID, 'senha')))
print("All elements located!")
except TimeoutException:
print("Loading took too much time!")
exit(0)
"""Scroll to our element """
driver.execute_script("arguments[0].scrollIntoView();", usuario)
""" Input data into our fields """
usuario.send_keys("username")
senha.send_keys("password")
""" Locate our login element """
login = WebDriverWait(driver, delay).until(EC.presence_of_element_located((By.ID, 'acessar')))
""" Click Login """
login.click()
To send the character sequence 123 to the password (senha) field, as the the desired elements are within a <frame> so you have to:
Induce WebDriverWait for the desired frame to be available and switch to it.
Induce WebDriverWait for the desired element to be clickable.
You can use the following solution:
Code Block:
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
options = webdriver.ChromeOptions()
options.add_argument("start-maximized")
options.add_argument('disable-infobars')
options.add_argument("--disable-extensions")
driver = webdriver.Chrome(chrome_options=options, executable_path=r'C:\WebDrivers\chromedriver.exe')
driver.get("https://directa.natal.rn.gov.br/")
WebDriverWait(driver, 10).until(EC.frame_to_be_available_and_switch_to_it((By.CSS_SELECTOR,"frame[name='mainsystem'][src^='main']")))
WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.CSS_SELECTOR, "input.input[name='usuario']"))).send_keys("Tads")
driver.find_element_by_css_selector("input.input[name='senha']").send_keys("123")
Browser Snapshot:
Here you can find a relevant discussion on Ways to deal with #document under iframe

Categories

Resources