I've seen similar post about this question with the resolution being using the WebDriverWait. But I still kept getting an exception error saying the selector is not present.
Even when I printed driver.execute_script("return document.body.innerHTML;" at the end of my code the full DOM didn't show up, it looks exactly like the page source, but I need the rest of the HTML's elements
from multiprocessing.connection import wait
from ntpath import join
import os
from xml.dom.minidom import Element
from selenium import webdriver
from selenium.webdriver.common.by import By ## Used for grabbing elements by
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.ui import WebDriverWait
import time
os.environ['PATH'] += ";C:\seleniumDrivers"
chrome = webdriver.Chrome()
chrome.get("https://jklm.fun/XSNM")
chrome.implicitly_wait(10)
name = chrome.find_element(By.CLASS_NAME, "nickname")
name.clear()
name.send_keys("Mr.Roboto")
btn = chrome.find_element(By.XPATH, '/html/body/div[2]/div[3]/form/div[2]/button')
btn.click()
join_btn = WebDriverWait(chrome, 1000000).until(EC.presence_of_element_located(
chrome.find_element(
By.XPATH, '/html/body/div[2]/div[3]/div[1]/div[1]/button')))
#join_btn = chrome.find_element(By.XPATH, '/html/body/div[2]/div[3]/div[1]/div[1]/button')
#join_btn = chrome.find_element(By.CSS_SELECTOR, 'button[data-text="joinGame"')
join_btn.click()
Element was in an iframe. I used chrome.switch_to.frame()
Related
Website link- https://demoqa.com/automation-practice-form/
I am trying to find xpath for an auto suggested option for Subject field
This is one way of interacting with that dropdown:
from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.support.ui import Select
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
chrome_options = Options()
chrome_options.add_argument("--no-sandbox")
chrome_options.add_argument('disable-notifications')
chrome_options.add_argument("window-size=1280,720")
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://demoqa.com/automation-practice-form/'
browser.get(url)
WebDriverWait(browser, 20).until(EC.element_to_be_clickable((By.ID, "subjectsInput"))).send_keys('m')
elusive_el = WebDriverWait(browser, 20).until(EC.element_to_be_clickable((By.CSS_SELECTOR, ".subjects-auto-complete__menu")))
print(elusive_el.get_attribute('outerHTML'))
maths_option = elusive_el.find_element(By.XPATH, "//div[text()='Maths']")
maths_option.click()
print('selected maths')
This should select the Math option, and also print in terminal the html structure of that element, so you can inspect them, and eventually select other child elements as well - you will have to send another string into that input field, wait for the dropdown to initialize, select another option.
Selenium docs: https://www.selenium.dev/documentation/
HTML of required element is
<div class="subjects-auto-complete__option subjects-auto-complete__option--is-focused css-1n7v3ny-option" id="react-select-2-option-0" tabindex="-1">Maths</div>
Try this one
//div[contains(#class, "subjects-auto-complete__option")]
I am also trying to find xpath for the 'subject' field to select multiple options.
I am able to send the text, but not able to select it from the dropdown.
Here is my code:
driver.findElement(By.id("subjectsInput")).sendKeys("M"); driver.findElement(By.xpath("//div[text()='Maths']")).click();
`Thread.sleep(1000);
Suggest me where I went wrong.
How to extract the text which is displayed as part of the link inside the span marker.
<span class="pull-left w-100 font30 medium_blue_type mb10"><a href='/XLY'>XLY</a></span> <span class="w-100">Largest Allocation</span>
Output:
XLY
I've tried several approaches, among all, using
elems = driver.find_elements_by_class_name("span.pull-left.w-100.font30.medium_blue_type.mb10")
elems = driver.find_element_by_xpath('.//span[#class = "pull-left w-100 font30 medium_blue_type mb10"]')
but can't get it working. The website is https://www.etf.com/stock/TSLA.
EDIT:
Is it possible to do it without opening the window in the browser, e.g. using "headless" option?
op = webdriver.ChromeOptions()
op.add_argument('headless')
driver = webdriver.Chrome(CHROME_DRIVER_PATH, options=op)
If you prefer to have a text-based locators, you can use the below:
//span[text()='Largest Allocation']/../span
You should click on the cookies I understand button first.
Make use of explicit waits.
So your effective code would be:
driver = webdriver.Chrome(driver_path)
driver.maximize_window()
wait = WebDriverWait(driver, 30)
driver.get("https://www.etf.com/stock/TSLA")
try:
wait.until(EC.element_to_be_clickable((By.LINK_TEXT, "I Understand"))).click()
print("Clicked on I understand button")
except:
pass
txt = wait.until(EC.visibility_of_element_located((By.XPATH, "//span[text()='Largest Allocation']/../span"))).text
print(txt)
Imports:
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
Output:
Clicked on I understand button
XLY
Process finished with exit code 0
If you are looking for locators not based on text, use the below line of code:
txt = wait.until(EC.visibility_of_element_located((By.XPATH, "(//span[contains(#class,'medium_blue_type')]//a)[2]"))).text
There are several possible problems here:
Maybe you are missing a delay
The locator you are using may be not unique
I can see here you are extracting the attribute value from the returned web element
The web element can be inside iframe etc.
Based on currently shared information you can try adding a wait and extracting the web element value as following:
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)
href = wait.until(EC.visibility_of_element_located((By.XPATH, "//span[#class = "pull-left w-100 font30 medium_blue_type mb10"]"))).get_attribute("href")
Use the following xpath to identify the href link.
//div[./span[text()='Largest Allocation']]//a
You need to induce some delay to get the element.
Use WebDriverWait() and wait for visibility of the element.
To get the text:
print(WebDriverWait(driver,10).until(EC.visibility_of_element_located((By.XPATH, "//div[./span[text()='Largest Allocation']]//a"))).text)
To get the href:
print(WebDriverWait(driver,10).until(EC.visibility_of_element_located((By.XPATH, "//div[./span[text()='Largest Allocation']]//a"))).get_attribute("href"))
you need to import below libraries.
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
I'm trying to click the buttons on the left-panel of the web-page I'm trying to scrape. However, by using Selenium, it seems to only click only on a few of these buttons. I have added a time.sleep between each click which did not make a difference.
I just get the following error:
NoSuchElementException: Message: no such element: Unable to locate element: {"method":"xpath","selector":"(//div[#class='toggle-bottom-filter'])[7]"}
I have double checked that path and it does exist on the website. So I'm not certain as to why it's undetectable, any ideas?
Here's my script:
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
import time
driver = webdriver.Chrome()
driver.get("https://www.theparking.eu/#!/used-cars/")
wait=WebDriverWait(driver,15)
wait.until(EC.visibility_of_element_located((By.CSS_SELECTOR, "#bloc-filter")))
wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR,"div[class='sd-cmp-25TOo'] span[class='sd-cmp-16t61 sd-cmp-2JYyd sd-cmp-3cRQ2']"))).click()
#WebDriverWait(driver, 10).until(EC.frame_to_be_available_and_switch_to_it((By.XPATH,"//iframe[#title='Electric car drivers will soon no longer be able to charge their cars here.']")))
stuff = []
for more in range(1, 9):
time.sleep(2)
driver.find_element(By.XPATH, f"(//div[#class='toggle-bottom-filter'])[{more}]").click()
data = driver.page_source
# ... parse with beautifulsoup
Not all the 9 elements you are trying to click are initially visible, you first will have to scroll the element into the view and only after that click them.
I see there are 11 elements matching //div[#class='toggle-bottom-filter'] locator there so possibly you should change the for loop to for more in range(1, 12):
I think the following code should work better:
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
from selenium.webdriver.common.action_chains import ActionChains
import time
driver = webdriver.Chrome()
driver.get("https://www.theparking.eu/#!/used-cars/")
wait=WebDriverWait(driver,15)
actions = ActionChains(driver)
wait.until(EC.visibility_of_element_located((By.CSS_SELECTOR, "#bloc-filter")))
wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR,"div[class='sd-cmp-25TOo'] span[class='sd-cmp-16t61 sd-cmp-2JYyd sd-cmp-3cRQ2']"))).click()
#WebDriverWait(driver, 10).until(EC.frame_to_be_available_and_switch_to_it((By.XPATH,"//iframe[#title='Electric car drivers will soon no longer be able to charge their cars here.']")))
stuff = []
for more in range(1, 12):
time.sleep(2)
button = driver.find_element(By.XPATH, f"(//div[#class='toggle-bottom-filter'])[{more}]")
actions.move_to_element(button).perform()
time.sleep(0.5)
button.click()
time.sleep(0.5)
data = driver.page_source
# ... parse with beautifulsoup
I'm trying to scroll to the end in this page url
When got into the page, I click the button 'Show all 77 products' I got into a popup that shows partially the elements into the popup. Actually this is my code:
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
from time import sleep
def getpage(driver):
driver.get('https://www.binance.com/it/pos')
sleep(3)
driver.find_element_by_xpath('//div[#id="savings-lending-pos-expend"]').click()
sleep(2)
elem = driver.find_element_by_xpath('//div[#class="css-n1ers"]')
elem.send_keys(Keys.END)
driver = webdriver.Firefox()
getpage(driver)
I have tried almost everything to work, apart from the solution in the code above, I tried with nu success the current solutions:
driver.execute_script("window.scrollTo(0, Y)")
and
driver.execute_script("window.scrollTo(0, document.body.scrollHeight);")
and in this solutions I didn't understand which label to use
label.sendKeys(Keys.PAGE_DOWN);
I tried almost all solutions but none worked. I hope you can help me. Thank you.
Try like below and confirm:
You can try to find each row and apply scrollIntoView for the same.
# Imports required for Explicit wait:
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By
def getpage(driver):
driver.get('https://www.binance.com/it/pos')
wait = WebDriverWait(driver,30)
wait.until(EC.element_to_be_clickable((By.ID,"savings-lending-pos-expend"))).click() // show more option
i = 0
try:
while True:
options = driver.find_elements_by_xpath("//div[#id='modal-wrapper']/div") // Try to find rows.
driver.execute_script("arguments[0].scrollIntoView(true);",options[i])
time.sleep(1)
i+=1
except IndexError as e:
print("Exception: {}".format(e.args[-1]))
print(i)
getpage(driver)
You can use ActionChains
from selenium.webdriver.common.action_chains import ActionChains
actions = ActionChains(driver)
actions.send_keys(Keys.PAGE_DOWN).perform()
That will make the page scroll down similar to pressing the Page Down key.
This solution worked:
from selenium import webdriver
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By
from time import sleep
def getpage(driver):
driver.get('https://www.binance.com/it/pos')
wait = WebDriverWait(driver,30)
wait.until(EC.element_to_be_clickable((By.ID,"savings-lending-pos-expend"))).click()
i = 0
sleep(5)
pop_up_window = WebDriverWait(driver, 2).until(EC.element_to_be_clickable((By.XPATH, "//div[#id='modal-scroller']")))
while True:
driver.execute_script('arguments[0].scrollTop = arguments[0].scrollTop + arguments[0].offsetHeight;', pop_up_window)
sleep(1)
driver = webdriver.Firefox()
getpage(driver)
I'm trying to use Selenium to log into ESPN. A solution that used to work is detailed here. In order to log in I need to find the frame that has the username and password fields and switch to that frame. Unfortunately, that numerical index of that frame isn't always the same. I decided to just try them all, but as soon as I've switched to one frame, switching to the next fails with selenium.common.exceptions.StaleElementReferenceException: Message: The element reference of <iframe class="ob-pifr"> stale: either the element is no longer attached to the DOM or the page has been refreshed. So I'm looking for
A way to switch frames without the StaleElementReferenceException
A way to check whether a frame is the one I want before I switch to it
Some other solution, though I'd prefer something introspective to a magic (and presumably fragile) formula like "It's always the third frame from the end)
Here's some sample code that leads to the StaleElementReferenceException:
from time import sleep
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 NoSuchElementException
driver = webdriver.Firefox(executable_path = '/usr/local/bin/geckodriver')
driver.get("http://games.espn.go.com/ffl/signin")
WebDriverWait(driver, 1000).until(EC.presence_of_all_elements_located((By.XPATH,"(//iframe)")))
elem = None
frms = driver.find_elements_by_xpath("(//iframe)")
print("Found {} frames", len(frms)) # Varies from 6 to 8
for count, frm in enumerate(frms):
print("Trying frm[{}]".format(count))
driver.switch_to.frame(frm)
sleep(2)
try:
# The command below will fail the second time around with
# `either the element is no longer attached to the DOM or the page has been refreshed`
elem = driver.find_element_by_xpath("(//input)[1]")
except NoSuchElementException:
pass
else:
break
Frame id is disneyid-iframe which opens the login popup So first you need to switch into it
driver.switch_to_frame(driver.find_element_by_id("disneyid-iframe"))
and then perform sendkeys like
driver.find_element_by_xpath("//input[#type='email']").send_keys("emailid")
driver.find_element_by_xpath("//input[#type='password']").send_keys("password")
Other way to switch in frame is ExplicitWait. It wait until frame available once there then it get switched in
wait = WebDriverWait(driver, 60)
wait.until(EC.frame_to_be_available_and_switch_to_it((By.ID, "disneyid-iframe")))
Your Final code will be :
from time import sleep
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 NoSuchElementException
driver = webdriver.Firefox(executable_path = '/usr/local/bin/geckodriver')
driver.get("http://games.espn.go.com/ffl/signin")
wait = WebDriverWait(driver, 60)
wait.until(EC.frame_to_be_available_and_switch_to_it((By.ID, "disneyid-iframe")))
driver.find_element_by_xpath("//input[#type='email']").send_keys("emailid")
driver.find_element_by_xpath("//input[#type='password']").send_keys("password")
driver.find_element_by_xpath("//button[#type='submit']").click()
Note : Please check syntax as per Python.