Capture elements with Selenium which are loaded lazy in Python - python

Trying to click a button with Selenium, but I keep getting an error:
NoSuchElementException: Message: no such element: Unable to locate
element: {"method":"link text","selector":"AGREE"}
Here's the button I am trying to click.
I assume, the popup is loaded lazy. I found some sources, but could not make it work. Here's my code
import pandas as pd
import bs4
import selenium as sel
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
import time
import os
driver = sel.webdriver.Chrome() #uses Chrome driver in usr/bin/ from https://chromedriver.chromium.org/downloads
url = 'https://fbref.com/en/squads/0cdc4311/Augsburg'
driver.get(url)
time.sleep(5)
html = driver.page_source
soup = bs4.BeautifulSoup(html, 'html.parser')
#click button -> accept cookies
element = driver.find_element(By.LINK_TEXT, "AGREE")
element.click()
>>> NoSuchElementException: Message: no such element: Unable to locate element: {"method":"link text","selector":"AGREE"}
I also tried
[...]
driver = sel.webdriver.Chrome() #uses Chrome driver in usr/bin/ from https://chromedriver.chromium.org/downloads
driver.implicitly_wait(10) # seconds'
[...]
and the popup is definitively there. But still get the same error.

What happens?
You try to select a <button> via .LINK_TEXT, "AGREE", what won't work, cause it is a <button> not a link.
How to fix?
Wait for the <button> selected by xpath to be clickable:
#click button -> accept cookies
element = WebDriverWait(driver, 3).until(EC.element_to_be_clickable((By.XPATH, '//button[text()="AGREE"]')))
element.click()

Related

Python - Using Selenium to Login to Web

I cannot login to this site with Selenium.
This is the url.
https://www.burn-cycle.com/my-account/pearl-district
What I tried:
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.common.by import By
import yaml
import time
conf = yaml.full_load(open("login_details.yml"))
my_burn_email = conf["user"]["email"]
my_burn_password = conf["user"]["password"]
driver = webdriver.Chrome()
driver.get("https://www.burn-cycle.com/my-account/pearl-district")
time.sleep(1)
username = driver.find_element(By.XPATH, "//*[#id='USERNAME']")
username.send_keys(my_burn_email)
pw = driver.find_element(By.XPATH, "//*[#id='PASSWORD']")
pw.send_keys(my_burn_password)
login_button = driver.find_element(By.XPATH("//*[#id='liFormWrap']/form[1]/button")).click()
The website loads (slowly) but nothing populates. This is the output:
selenium.common.exceptions.NoSuchElementException: Message: no such element: Unable to locate element: {"method":"xpath","selector":"//*[#id='USERNAME']"}
(Session info: chrome=103.0.5060.134)
What am I doing wrong?
You need to wait for the website to load completely so that you can fetch those elements from the webpage, you can achieve this by using implicitly.wait(#amount of second) command right after initializing the web driver.
driver = webdriver.Chrome()
driver.implicitly_wait(15) # gives an implicit wait for 15 seconds
the element is under iframe, you need try this way, first switch into iframe,
see this link
driver.get("https://www.burn-cycle.com/my-account/pearl-district")
time.sleep(5)
iframe = driver.find_element(By.XPATH, "//*[#id='sf-frame']")
# switch to selected iframe
driver.switch_to.frame(iframe)
username = driver.find_element(By.XPATH, "//input[#data-val-required='Username is required']")
username.send_keys("test")

Unable to locate element: {"method":"xpath","selector":"/html/body/div/div[2]/div[3]/div[2]/button"}

So im Trying to make a discord bot that sends news from selected news services, and Ive got it working on every website, except Bild.de. They have got a banner you have to accept before accesing the website, and I cant get past that. Like I said, I had no problems on any other website, but this one.
My code (python):
import time
from selenium import webdriver
# selenium part
url = 'https://www.bild.de/home/newsticker/news/alle-news-54190636.bild.html'
browser = webdriver.Chrome()
browser.get(url)
time.sleep(5)
#trying to accept cookie banner
browser.find_element_by_xpath(
"/html/body/div/div[2]/div[3]/div[2]/button").click()
Error Message
selenium.common.exceptions.NoSuchElementException: Message: no such element: Unable to locate element: {"method":"xpath","selector":"/html/body/div/div[2]/div[3]/div[2]/button"}
Things to be noted down here.
Cookies button is in iframe, so first we have to switch to iframe in Selenium.
I am using execute script to click on it.
Remember to switch back to default content when you are done with the iframe.
Code :
driver = webdriver.Chrome(driver_path)
driver.maximize_window()
driver.implicitly_wait(50)
driver.get("https://www.bild.de/home/newsticker/news/alle-news-54190636.bild.html")
wait = WebDriverWait(driver, 20)
wait.until(EC.frame_to_be_available_and_switch_to_it((By.CSS_SELECTOR, "iframe[title='SP Consent Message']")))
button = wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR, "div.message-component.message-row.mobile-reverse>div:nth-child(2)>button")))
driver.execute_script("arguments[0].click();", button)
Imports :
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC

Python selenium How to click an element in iframe?

My first test with selenium is to click a button on a website. The first button that I need to click is this "yes you can use cookies"-buttons in the popup of a website. But it seems that selenium doesn't find that button even though I added a wait line. I tried other buttons in the popup as well, but none of them can be found by my element_to_be_clickable. The element is in an iframe, so I guess I have to change to it, but it seems that I'm doing something wrong.
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_path = "D:/Python/learning_webclicker/firefox_driver/geckodriver.exe"
firefox_path = "C:/Program Files/Mozilla Firefox/firefox.exe"
option = webdriver.FirefoxOptions()
option.binary_location = firefox_path
driver = webdriver.Firefox(executable_path=driver_path, options=option)
url = "https://web.de/"
driver.get(url)
WebDriverWait(driver,10).until(EC.frame_to_be_available_and_switch_to_it(driver.find_element_by_xpath("/html/body/div[2]/iframe")))
#I tried to find the "save-all-conditionally"-element with lots of different methods:
WebDriverWait(driver, 10).until(EC.element_to_be_clickable((By.ID, "save-all-conditionally"))).click()
#WebDriverWait(driver, 10).until(EC.element_to_be_clickable((By.XPATH, """//*[#id="save-all-conditionally"]"""))).click()
#WebDriverWait(driver, 10).until(EC.visibility_of_element_located((By.ID, "save-all-conditionally")))
# ...
This raises the error
selenium.common.exceptions.TimeoutException: Message:
And if I try to click the button directly after changing to iframe (or without checking for iframe), then I get
driver.implicitly_wait(10)
element=driver.find_element_by_xpath("""//*[#id="save-all-conditionally"]""")
element.click()
>>> selenium.common.exceptions.NoSuchElementException: Message: Unable to locate element: [id="save-all-conditionally"]
I guess, that I'm not really in the iframe (although frame_to_be_available_and_switch_to_it doesn't return an error), but I'm not sure how/what/why.
The element you are looking after is inside nested iframe. You need to switch both the
iframes.
Use following css selector to identify the iframe.
WebDriverWait(driver,10).until(EC.frame_to_be_available_and_switch_to_it((By.CSS_SELECTOR,"iframe[name='landingpage']")))
WebDriverWait(driver,10).until(EC.frame_to_be_available_and_switch_to_it((By.CSS_SELECTOR,"iframe[src*='plus.web.de']")))
WebDriverWait(driver, 10).until(EC.element_to_be_clickable((By.ID, "save-all-conditionally"))).click()
Or Use below xpath to identify the iframe.
WebDriverWait(driver,10).until(EC.frame_to_be_available_and_switch_to_it((By.XPATH,"//iframe[#name='landingpage']")))
WebDriverWait(driver,10).until(EC.frame_to_be_available_and_switch_to_it((By.XPATH,"//iframe[contains(#src,'plus.web.de')]")))
WebDriverWait(driver, 10).until(EC.element_to_be_clickable((By.ID, "save-all-conditionally"))).click()

How to make Selenium click on this button?

I am trying to extract all articles on this web page, but i can't make Selenium click on the "Continue" button at the end of the page.
I have tried a lot of different versions, but i'll post just the one, which at least doesn't throw an error...:
import time
from selenium import webdriver
from selenium.webdriver.common.action_chains import ActionChains
addr = 'https://www.armani.com/de/armanicom/giorgio-armani/f%C3%BCr-ihn/alle-kleidungsstucke'
options = webdriver.ChromeOptions()
options.add_argument("--enable-javascript")
driver = webdriver.Chrome(options=options)
driver.get(addr)
ContinueButton = driver.find_element_by_xpath("//li[#class='nextPage']")
# gives: No error, but also no effect
# ContinueButton = driver.find_element_by_xpath("/html/body/div[3]/main/section/div[2]/div[1]/ul/li[8]/a/span[2]")
# gives: NoSuchElementException: no such element: Unable to locate element: {"method":"xpath","selector":"/html/body/div[3]/main/section/div[2]/div[1]/ul/li[8]/a/span[2]"}
#ContinueButton = driver.find_element_by_css_selector(".nextPage > a:nth-child(1)")
# gives: NoSuchElementException: no such element: Unable to locate element:
ActionChains(driver).move_to_element(ContinueButton).click()
time.sleep(5)
Chrome engine is v86, but i have tried (and failed) with Firefox as well.
You want to wait for the element to be clickable and then attempt to click on it:
I
import time
from selenium import webdriver
from selenium.webdriver.common.action_chains import ActionChains
addr = 'https://www.armani.com/de/armanicom/giorgio-armani/f%C3%BCr-ihn/alle-kleidungsstucke'
options = webdriver.ChromeOptions()
options.add_argument("--enable-javascript")
driver = webdriver.Chrome(options=options)
driver.get(addr)
ContinueButton = WebDriverWait(driver, 20).until(
EC.element_to_be_clickable((By.XPATH, "//li[#class='nextPage']/a")))
ActionChains(driver).move_to_element(ContinueButton).click()
time.sleep(5)
The problem is that you are clicking on the li element.
Your click is received but no action is performed, in order to do so you need to target the a element after the li.
Try this:
ContinueButton = driver.find_element_by_xpath("//li[#class='nextPage']/a")

Select element from a list inside an iframe using python selenium

I would like to write a python Programm which downloads automaticaly historical stock data from a web-page. The correspindent HTML-Code of the Element I would like to select is on the following Picture:
There are two iframes. One is inside the other. I switch to the second iframe, but the element I would like to click can't be found. I get the following error: "Message: no such element: Unable to locate element: {"method":"css selector","selector":"[id=":cu"]"} (Session info: chrome=75.0.3770.100)"
from requests import get
from requests.exceptions import RequestException
from contextlib import closing
from bs4 import BeautifulSoup
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
import ctypes # An included library with Python install.
import time
user = ""
pwd = ""
driver = webdriver.Chrome()
driver.get("https://www.dukascopy.com/trading-tools/widgets/quotes/historical_data_feed")
driver.maximize_window()
## Give time for iframe to load ##
time.sleep(1)
# get the list of iframes present on the web page using tag "iframe"
seq = driver.find_elements_by_tag_name('iframe')
print("No of frames present in the web page are: ", len(seq))
#switch to correct iFrame
driver.switch_to_default_content()
iframe = driver.find_elements_by_tag_name('iframe')[1]
driver.switch_to.frame(iframe)
driver.implicitly_wait(5)
elem = driver.find_element_by_id(':cu')
elem.click()
ctypes.windll.user32.MessageBoxW(0, "Test", "Test MsgBox", 1)
driver.close()
If my code would be correct the element "EUR/TRY" in the List would be selected.
There are total 4 iframes.
The table you want to interact with is in iframe[src^='https://freeserv'] and parent iframe is widget-container. One by one you have to switch to it like this :
Code :
wait = WebDriverWait(driver,10)
driver.maximize_window()
driver.get("https://www.dukascopy.com/trading-tools/widgets/quotes/historical_data_feed")
wait.until(EC.frame_to_be_available_and_switch_to_it((By.ID, "widget-container")))
wait.until(EC.frame_to_be_available_and_switch_to_it((By.CSS_SELECTOR, "iframe[src^='https://freeserv']")))
check_Box = wait.until(EC.visibility_of_element_located((By.XPATH, "//strong[text()='EUR/TRY']/../preceding-sibling::span/span")))
ActionChains(driver).move_to_element(check_Box).perform()
check_Box.click()

Categories