I'm trying to scroll down the popup window here: (note you'll need to click any food item on the page to bring up the popup in question)
https://www.just-eat.co.uk/restaurants-mcdonalds-claphamjunction/menu
I've tried to scroll down this popup using the below code, first identifying the popup scrollbar using its css selector and then sending arrow down keys to it.
popup = browser.find_element_by_css_selector("body > div:nth-child(3) > div:nth-child(4) > div.c-megaModal.MegaModal_c-megaModal_3w2Fg.u-overlay.c-itemSelector.c-modal--popUp--belowMid.is-fullHeight")
popup.send_keys(Keys.ARROW_DOWN)
However, I get the following error message:
selenium.common.exceptions.ElementNotInteractableException: Message: element not interactable
I managed to scroll down fine using FireFox but I can't get it to work on Chrome (need to use Chrome for other reasons).
Any help would be appreciated
EDIT:
I tried the following but it's not scrolling (no error message appears it just passes through the code without scrolling).
wait = WebDriverWait(browser, 20)
for _ in range(8):
wait.until(EC.visibility_of_element_located(
(By.XPATH, "//div[contains(#class,'MegaModal_c-megaModal-document--scrollable')]")))
browser.execute_script(
"document.querySelector('div[class*=MegaModal_c-megaModal-document--scrollable]').scrollDown += 250")
You are using a wrong locator
This element is not directly interactable by user. This is why you can't send keys to it with Selenium.
Instead of sending arrow keys to that element you can scroll it with JavaScript executor.
Please try this
wait.until(EC.visibility_of_element_located((By.XPATH, "//div[contains(#class,'MegaModal_c-megaModal-document--scrollable')]")))
driver.execute_script("document.querySelector('div[class*=MegaModal_c-megaModal-document--scrollable]').scrollDown += 250")
In order to use explicit conditions as above you will need these imports
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
And to initialize wait object
wait = WebDriverWait(driver, 20)
Related
I have a script that uses Selenium (Python).
I tried to make the code click a button that it acknowledges is clickable, but throws an error stating it;s not clickable.
Same thing happens again in a dropdown menu, but this time I'm not clicking, but selecting an option by value.
from selenium import webdriver
from webdriver_manager.chrome import ChromeDriverManager
from selenium.webdriver.common.by import By
from selenium.webdriver.support.select import *
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
# Getting to Chrome and website
website = 'https://www.padron.gob.ar/publica/'
driver = webdriver.Chrome(ChromeDriverManager().install())
driver.get(website)
driver.maximize_window()
#"BUENOS AIRES" in "Distrito Electoral"
distritoElectoralOptions = driver.find_element(By.NAME, 'site')
Select(distritoElectoralOptions).select_by_value('02 ')
#Clicking "Consulta por Zona
WebDriverWait(driver, 35).until(EC.element_to_be_clickable((By.ID, 'lired')))
consultaPorZona = driver.find_element(By.ID, 'lired')
consultaPorZona.click()
#"SEC_8" in "Sección General Electoral"
WebDriverWait(driver, 35).until(EC.visibility_of((By.NAME, 'secg')))
seccionGeneralElectoral = driver.find_element(By.NAME, 'secg')
Select(seccionGeneralElectoral).select_by_value('00008')
I'm getting this error on line 21:
selenium.common.exceptions.ElementNotInteractableException: Message: element not interactable: element has zero size
It works in a ipython notebook if each section is separated, but only if the option "Run all" is not used. Instead, the kernel has to be run on it's own.
I'm using VS Code.
Also, when it reaches the last line, when run in ipynb format, it throws this error:
Message: Cannot locate option with value: 00008
Thank you in advance.
When a web element is present in the HTML-DOM but it is not in the state that can be interacted. Other words, when the element is found but we can’t interact with it, it throws ElementNotInteractableException.
The element not interactable exception may occur due to various reasons.
Element is not visible
Element is present off-screen (After scrolling down it will display)
Element is present behind any other element
Element is disabled
If the element is not visible then wait until element is visible. For this we will use wait command in selenium
wait = WebDriverWait(driver, 10)
element = wait.until(EC.element_to_be_clickable((By.ID, 'someid')))
element.click()
If the element is off-screen then we need to scroll down the browser and interact with the element.
Use the execute_script() interface that helps to execute JavaScript methods through Selenium Webdriver.
browser = webdriver.Firefox()
browser.get("https://en.wikipedia.org")
browser.execute_script("window.scrollTo(0,1000)") //scroll 1000 pixel vertical
Reference this solution in to the regarding problem.
Trying to click on this button
Tried:
driver.find_element(By.XPATH, '//*[#id="signup_with_facebook"]/button').click()
Error:
selenium.common.exceptions.ElementNotInteractableException: Message: element not interactable
Tried:
button = driver.find_element(By.XPATH, '//*[#id="signup_with_facebook"]/button')
ActionChains(driver).move_to_element(
button
).click(
button
).perform()
Error:
selenium.common.exceptions.ElementNotInteractableException: Message: element not interactable: [object HTMLButtonElement] has no size and location
How to do this?
Code:
driver = webdriver.Chrome(executable_path='chromedriver')
driver.get('https://www.myheritage.com/deep-nostalgia')
driver.find_element(By.XPATH, '//*[#id="masterPageHeader"]/div/div[3]/div/div[2]/div[1]/div[2]/a[1]/span').click()
driver.implicitly_wait(10)
wait = WebDriverWait(driver, 20)
wait.until(EC.visibility_of_element_located((By.XPATH, '//*[#id="signup_with_facebook"]/button'))).click()
Error:
selenium.common.exceptions.TimeoutException: Message:
There are two buttons with the same #id: first one inside signupContainer (the one that you're trying to click), second - in loginContainer. You need to select second one. To do so use this XPath:
'//div[#id="loginContainer"]//div[#id="signup_with_facebook"]/button'
Looks like you are trying to click this element while the page is still not fully rendered.
Try adding an Explicit Wait to wait for this element visibility before clicking it, something like this:
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)
wait.until(EC.visibility_of_element_located((By.XPATH, '//*[#id="signup_with_facebook"]/button'))).click()
P.S. I can't validate the locator you are using here and the entire code correctness since you didn't share all your code.
UPD
After you added your code I can see that:
You should add an explicit wait before clicking the login button.
You should improve the login button locator.
You should not mix explicit waits with implicitly waits.
The locator you are using '//*[#id="signup_with_facebook"]/button' is not unique, it should be fixed.
This should work better:
driver = webdriver.Chrome(executable_path='chromedriver')
driver.get('https://www.myheritage.com/deep-nostalgia')
wait = WebDriverWait(driver, 20)
wait.until(EC.visibility_of_element_located((By.XPATH, "//div[#class='user_strip_end']//a[#class='user_strip_item user_strip_item_1']"))).click()
wait.until(EC.visibility_of_element_located((By.CSS_SELECTOR, '#loginContainer button.facebook_login_button'))).click()
i have been trying to click an input as type: checkbox but it doesn't seem to work. I need to press one of the size options but when i expand the size-picker-form using this piece of code:
sizelistspot = WebDriverWait(driver, 10).until(EC.presence_of_element_located((By.XPATH, '//*[#id="picker-trigger"]'))) sizelistspot = driver.find_element(By.XPATH, '//*[#id="picker-trigger"]').click()
and then use this piece of code to check if the form is located:
sizelist = WebDriverWait(driver, 10).until(EC.presence_of_element_located((By.NAME, 'size-picker-form'))) print('I found the size menu!!!')
I watch it run because i run non-headless and i see the dropdown menu expand so then i try to select a size with this piece of code:
sizechoice = driver.find_element(By.ID, 'size-picker-JOC12N001-A180150000').click() print('I selected the size!!!')
But i recieve the error: 'selenium.common.exceptions.ElementNotInteractableException: Message: element not interactable' Why can't i click the size whilst i can manually? And what is the right way to do it. This is the link to the site: https://www.zalando.nl/jordan-air-jordan-1-mid-sneakers-hoog-joc12n001-a18.html I am still a beginner so there is a big chance there are some mistakes in my code. Thanks!
//div[./*[#id='size-picker-JOC12N001-A180150000']]
Just click the div that contains that id instead the input tag has 0x0 size and doesn't seem to be interactable.
wait=WebDriverWait(driver,60)
driver.get('https://www.zalando.nl/jordan-air-jordan-1-mid-sneakers-hoog-joc12n001-a18.html')
wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR,"#uc-btn-accept-banner"))).click()
sizelistspot = wait.until(EC.element_to_be_clickable((By.XPATH, '//*[#id="picker-trigger"]')))
sizelistspot.click()
wait.until(EC.element_to_be_clickable((By.XPATH, '//div[./*[#id="size-picker-JOC12N001-A180150000"]]'))).click()
Imports:
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
Outputs:
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])
So I'm scraping using selenium and I want to click 'next' button in 'Defensive' section but the code I wrote clicks 'next' on 'Summary'.
Here's the url for you to try :
https://www.whoscored.com/Regions/252/Tournaments/2/Seasons/7361/Stages/16368/PlayerStatistics/England-Premier-League-2018-2019
So it's selecting 'Defensive' and I can see it selected in the window but the next page doesnt appear. On clicking 'Summary' I found out next function is actually happening there.
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
browser= webdriver.Chrome(executable_path ="C:\Program Files (x86)\Google\Chrome\chromedriver.exe")
browser.get('https://www.whoscored.com/Regions/252/Tournaments/2/Seasons/7361/Stages/16368/PlayerStatistics/England-Premier-League-2018-2019')
browser.find_element_by_xpath("""//*[#id="stage-top-player-stats-options"]/li[2]/a""").click()
element = WebDriverWait(browser, 20).until(EC.presence_of_element_located((By.XPATH, """//*[#id="next"]""")))
browser.execute_script("arguments[0].click();", element)
The xpath for next button is not unique for this page. try this,
element = WebDriverWait(browser, 20).until(EC.presence_of_element_located((By.XPATH, "//*[#id='stage-top-player-stats-defensive']//a[#id='next']")))
browser.execute_script("arguments[0].click();", element)
or
element = WebDriverWait(browser, 20).until(EC.presence_of_element_located((By.XPATH, "//*[#id='stage-top-player-stats-defensive']//a[#id='next']")))
element.click()
For each tab (Summary, Defensive, ..) new next button with same id=next added to the DOM.
Select Defensive and you will see there will be two next buttons with same id=next, select Offensive and there will be three next buttons.
With basic id=next selector you always click to the first next button from Summary tab. Because you're using JavaScript and nothing happen, try to click with Selenium click method and you will get an error.
To solve the problem adjust your selector to be more specific to the dom - #statistics-paging-defensive #next.
Also when you first time open the page there's cookies acceptance screen appears and block the page, you can use method like below to skip it.
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 selenium.common.exceptions as EX
def accept_cookies():
try:
WebDriverWait(browser, 20)\
.until(EC.element_to_be_clickable((By.CSS_SELECTOR, "button.qc-cmp-button")))\
.click()
except EX.NoSuchElementException or EX.TimeoutException:
pass
#...
browser = webdriver.Chrome(executable_path ="C:\Program Files (x86)\Google\Chrome\chromedriver.exe")
browser.get('https://www.whoscored.com/Regions/252/Tournaments/2/Seasons/7361/Stages/16368/PlayerStatistics/England-Premier-League-2018-2019')
wait = WebDriverWait(browser, 20)
browser.get(baseUrl)
accept_cookies()
wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR, "[href='#stage-top-player-stats-defensive']"))).click()
next_button = wait.until(
EC.element_to_be_clickable((By.CSS_SELECTOR, "#statistics-paging-defensive #next")))
next_button.click()
Your elements locators must be unique
Avoid using XPath wildcards - * as it will cause performance degradation and prolonged elements lookup timings
Avoid using JavaScriptExecutor for clicking, well-behaved Selenium test must do what real user does and I doubt that real user will be opening browser console and typing something like document.getElementById('next').click(), he will use the mouse
Assuming all above you should come up with a selector which uniquely identifies next button on Defensive tab which would be something like:
//div[#id='statistics-paging-defensive']/descendant::a[#id='next']
References:
XPath Tutorial
XPath Axes
XPath Operators & Functions