How to select an option from dropdown - python

I have a problem navigating a website using selenium. This is my code:
from selenium import webdriver
driver = webdriver.Firefox()
driver.get('https://webtrader.binary.com/v2.2.8/main.html#')
resources = driver.find_element_by_id('ui-id-1')
resources.click()
However, I get the exception:
selenium.common.exceptions.ElementNotInteractableException: Message: Element <ul id="ui-id-1" class="ui-menu ui-widget ui-widget-content ui-menu-icons"> could not be scrolled into view
I don't understand where I went wrong. I am trying to access 'Historical data' from the dropdown menu labeled "Resources". Could someone please help me access it. Maybe I got the id for Resources wrong. You could also check that out.

The element you want to click to open the dropdown is the previous sibling of the element resources
from selenium.webdriver.support import expected_conditions as ec
from selenium.webdriver.support.select import By
from selenium.webdriver.support.ui import WebDriverWait
wait = WebDriverWait(driver, 10)
driver.find_element_by_class_name('resources').click()
historical_data = wait.until(ec.visibility_of_element_located((By.ID, 'ui-id-4')))

There are many things happening here. First of all, your code is lacking a wait. Without it will always fail, as the page is dynamically loaded. Read about Waits.
Secondly, here resources = driver.find_element_by_id('ui-id-1') you are finding the element from the dropdown menu, and then you are trying to click it. But the dropdown menu is not opened. You should click on it, then wait for the option to appear, only then click on the 'Historical data'.

Related

Unable to select a menu item with selenium

I am making a screen scraper using the Selenium Python library and I have already made some code so that I can log in. For some reason I am now stuck on the main menu and can't select any of the options. I have tried using CSS Selector, Class Name, and XPATH and none have been able to select any of the possible choices. No matter what happens, I always get a TimeoutException even with a long delay.
The portion of the page I am trying to scrape from is here.
The relevant code is as follows:
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
# Open browser and go to the Webex login page
driver = webdriver.Chrome()
driver.get('https://admin.webex.com')
delay = 10 # seconds
long_delay = 20
# Login portion removed
# Menu selection goes here.
# I have tried the following with no luck
# The following lines produce a TimeoutException error
# Selecting menu item
WebDriverWait(driver, long_delay).until(EC.presence_of_element_located((By.XPATH, "span[#class='left-nav-item__link']"))).click()
WebDriverWait(driver, long_delay).until(EC.presence_of_element_located((By.XPATH, '//mch-left-nav-item-group[4]/ul/mch-left-nav-item[3]/li/span'))).click()
WebDriverWait(driver, long_delay).until(EC.presence_of_element_located((By.XPATH, "//webex-root/webex-main[#class='control-hub-container']//webex-sidebar/mch-left-nav/nav/mch-left-nav-item-group[4]/ul/mch-left-nav-item[3]//span[#class='left-nav-item__link']"))).click()
WebDriverWait(driver, long_delay).until(EC.presence_of_element_located((By.CSS_SELECTOR, "span[class='left-nav-item__link']"))).click()
WebDriverWait(driver, delay).until(EC.presence_of_element_located((By.CSS_SELECTOR, "[aria-label] mch-left-nav-item-group:nth-of-type(4) mch-left-nav-item:nth-of-type(3) .left-nav-item__link"))).click()
# Selecting group of items
WebDriverWait(driver, delay).until(EC.presence_of_all_elements_located((By.CLASS_NAME, 'left-nav-item')))
WebDriverWait(driver, delay).until(EC.presence_of_all_elements_located((By.CSS_SELECTOR, 'li.left-nav-item')))
# Selecting parent
WebDriverWait(driver, long_delay).until(EC.presence_of_element_located((By.CSS_SELECTOR, "li[data-test-name='calling']")))
Does anyone have an idea why I'm not able to select any element?
Try xpath for the third one:
WebDriverWait(driver, long_delay).until(EC.presence_of_element_located((By.XPATH, "span[#class='left-nav-item__link']"))).click()
To anyone having this issue.
When a new tab is opened while you are using Selenium, even though you are viewing the new page, Selenium is not. You have to switch to the correct window. Something such as the following can help you with that.
driver.switch_to.window(driver.window_handles[NUMBER])

Cannot click a button because Selenium is unable to locate an element

I have tried to make my script click the Purchase/Buy Family button on the Spotify Checkout Page. No matter what class, CSS, XPath, ID, or whatever I put in, it's just saying it could not find the object.
This is the button. It's not in an iframe:
<div class="sc-fzXfOu cvoJMt">
<button id="checkout_submit" class="Button-oyfj48-0 kaOWUo sc-fzXfOv tSdMK">
Buy Premium Family
</button>
</div>
My code:
time.sleep(3)
buy = driver.find_element_by_xpath("/html/body/div[3]/div/div/div/div/div/div/div[3]/div/div/div[2]/form/div[2]/button").click()
I am able to click the button,by a different xpath
driver.findElement(By.xpath("//button[#id='checkout_submit']")).click();
Edit -
Your xpath also works for me only when i load the page initially and there is no change in the dom - /html/body/div[3]/div/div/div/div/div/div/div[3]/div/div/div[2]/form/div[2]/button
It doesn't work when some new event or error is displayed and the dom structure changes.
Why use such relative XPath when the element has distinguishable attributes?
The problem here is the form is not static you have to wait loading of all elements.
And page loads with pane to accept cookies who can mask elements you want to run action on.
The best way in that case is first accept cookies and then run all actions you need.
Try to adapt this code for your needs, that run with success on my test.
In case you run this code you have to brake execution to login first, when the driver get the page.
from selenium import webdriver
from selenium.webdriver.common.action_chains import ActionChains
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.remote.webelement import WebElement
# change this line
path_driver = "your_path_to_chrome_driver"
by, buy_selector, cookies_selector = By.CSS_SELECTOR, 'button#checkout_submit', "button#onetrust-accept-btn-handler"
driver = webdriver.Chrome(path_driver)
driver.maximize_window()
actions = ActionChains(driver)
driver.get("https://www.spotify.com/us/purchase/offer/premium-family/?country=US")
# wait for loading buy button
sls = wait.until(EC.presence_of_all_elements_located((by, buy_selector)))
if sls:
# get accept cookies button element and click
cookies_accept = driver.find_element_by_css_selector(cookies_selector)
if isinstance(cookies_accept, WebElement):
cookies_accept.click()
# get buy button element, move to element and click
buy = driver.find_element_by_css_selector(buy_selector)
if isinstance(buy, WebElement) and buy.is_displayed() and buy.is_enabled():
actions.move_to_element(buy).click(buy).perform()

Selenium with Python : how to click dojo combobox values

I'm navigating a JS-heavy webpage with Selenium and I need to be able to interact with a dojo component on the page. The page I'm looking at has a dojo dijit form with a combobox that has subject names for my university. I want to expose and iteratively click on every item in the list in order to scrape the course names for that subject when it redirects. The list items are exposed when the dropdown arrow button is clicked.
the url I'm automating: http://sis.rutgers.edu/soc/#subjects?semester=12020&campus=NB,NK,CM&level=U,G
I'm inspecting the element for the dropdown button and copying the XPath.
dropdownButton = driver.find_element_by_xpath('//*[#id="widget_dijit_form_FilteringSelect_0"]/div[1]/input')
Running this yields:
NoSuchElementException: Message: no such element: Unable to locate
element:
{"method":"xpath","selector":"//*[#id="widget_dijit_form_FilteringSelect_0"]/div[1]/input"}
EDIT: I've made some progress, turn out the element wasn't rendered by the time find_by_xpath was called. I added a wait in my program, and now Selenium is able to locate and click the drowdown button.
Use WebDriverWait to wait require element conditions. Dropdown disappears on any action on the page, that's why to get option locator you can do one of the following:
all options loaded after first expand, that's why you can search option element by text in chrome dev tools and get locator
pause and inspect the element.
You can google best practice for locators,here and here.
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()
wait = WebDriverWait(driver, 10)
with driver:
driver.get("http://sis.rutgers.edu/soc/#subjects?semester=12020&campus=NB,NK,CM&level=U,G")
wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR, "#filteringSelectDiv .dijitArrowButtonInner"))).click()
options = driver.execute_script('return [...arguments[0]].map(e=>e.textContent)',
wait.until(EC.presence_of_all_elements_located(
(By.CSS_SELECTOR, ".dijitComboBoxMenuPopup .dijitMenuItem[item]"))))
for option in options:
driver.find_element_by_css_selector(".dijitInputInner").clear()
driver.find_element_by_css_selector(".dijitInputInner").send_keys(option, Keys.TAB)
wait.until(lambda d: d.execute_script("return document.readyState === 'complete'"))
# collect data

Frame Switch to click on a Box (Python Selenium)

I have a problem trying to automate my browser with Selenium on Python. It's been several hours that I block, and since I'm a beginner .. :(
I explain my problem:
I have to reach click on a box of Recaptcha. To do this, my bot must click on a button on the site, which then displays the recaptcha that I have to validate.
Here are the source page screenshot:
The popup of the recaptcha, in which the checkbox is located
The location of the checkbox that I have to click
I try this code:
time.sleep(5)
browser.switch_to_frame(browser.find_element_by_tag_name("CaptchaPopup"))
browser.switch_to_frame(browser.find_element_by_tag_name("iframe"))
CheckBox = WebDriverWait(browser, 10).until(
browser.find_element_by_id('recaptcha-anchor').click())
time.sleep(0.7)
CheckBox.click()
But the latter returns me an error :(
selenium.common.exceptions.NoSuchFrameException: Message: no such frame
I use Python 2.7.
Do you have a solution ?
Thank you very much in advance!
Try to use below code to handle required check-box:
from selenium.webdriver.support.ui import WebDriverWait as wait
from selenium.webdriver.support import expected_conditions as EC
wait(browser, 10).until(EC.frame_to_be_available_and_switch_to_it(browser.find_element_by_xpath('//iframe[contains(#src, "google.com/recaptcha")]')))
wait(browser, 10).until(EC.element_to_be_clickable((By.ID, 'recaptcha-anchor'))).click()

Use selenium to click and view more text

I'm very new to Selenium.
I'm crawling data from this page. I need to scroll down the page and click on "Load More Arguments" to get more text. This is the location to click on.
<a class="debate-more-btn" href="javascript:void(0);" onclick="loadMoreArguments('15F7E61D-89B8-443A-A21C-13FD5EAA6087');">
Load More Arguments
</a>
I have tried this code but it does not work. Should I need more code to locate to that (I think the 1 has already tell the location to click). Do you have any recommendation? Thank you in advance.
[1] btn_moreDebate = driver.find_elements_by_class_name("debate-more-btn")
[2] btn.click()
Find the link by link text, move to the element and click:
from selenium.webdriver.common.action_chains import ActionChains
link = driver.find_element_by_link_text('Load More Arguments')
ActionChains(browser).move_to_element(link).perform()
link.click()
If you get an exception while finding an element, you may need to use an Explicit Wait:
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
link = WebDriverWait(driver, 10).until(EC.element_to_be_clickable((By.LINK_TEXT, "Load More Arguments")))
ActionChains(browser).move_to_element(link).perform()
link.click()
If I understand your code correctly, I can see a few things wrong.
1. You're using find_elements_by_class_name. I'd recommend using find_element_by_class_name instead. elements returns a list, which isn't needed in a case where there is only one element.
2. You're using btn_moreDebate as the holder for the results of your find_elements, but then interacting with btn.
You should be able to perform the find and click in one action:
driver.find_element_by_class_name("debate-more-btn").click()

Categories