Selenium - Visibility of element in HTML page (Python) - python

I'm trying to scrape the following URL: https://www.vivareal.com.br/venda/sp/holambra/imovel-comercial_comercial/. It has two pages only. However, there is a button in the bottom which I can locate via XPATH: "//*[contains(#title, "Página anterior")]".
I'm trying to set a variable for when the button is not clickable, like:
WebDriverWait(driver, 10).until(EC.element_to_be_clickable((By.XPATH, '//*[contains(#title, "Página anterior")]')))
But it returns an element, even if the element is not clickable (I'm testing manually too). Is there any sugestions? Thanks!

When the button is not clickable, it has an attribute called data-disabled; otherwise that attribute is missing. The attribute has no value, but if you use the following CSS Selector it should grab that element only if there is no data-disabled attribute:
driver.find_element_by_css_selector('a[title="Página anterior"]:not([data-disabled]')

Related

I'm unable to locate the element to perform actions on it

I'm facing an issue locating the element on screen when there are no unique identifiers like ID, text etc. As it opens URL, I need to scroll down and click on button - 'Get Started' to proceed!...
Below is my code:
global driver
driver = webdriver.Chrome(ChromeDriverManager().install())
driver.maximize_window()
driver.get("https://My URL")
driver.implicitly_wait(10)
screen = driver.find_element(By.XPATH, '//div[#class="swiper-wrapper"]')
screen.click() (- This step doesnt through any error, i tried using this to scroll down the screen)
element = driver.find_element(By.XPATH, '//span[contains(text(),"Get Started")]')
driver.execute_script("arguments[0].scrollIntoView(true);", element )
WebDriverWait(driver, 10).until(EC.element_to_be_clickable((By.XPATH, '//span[contains(text(),"Get Started")]'))).click()
or
element.click()
Please help me in determining how to locate the element.
enter image description here
In this case you are trying to find span which is inside #shadow-root, Selenium won't be able to click elements inside #shadow-root in easy way. Look here: How to click button inside #shadow-root (closed) using Selenium and Python
But in your case you probably don't need/want to click this specific span, becouse you have custom element ion-button, which has some click event listener attached to it.
You can check XPATH value in browser devtools. If you go to Elements tab, you can right click desired element and choose option Copy>Copy Xpath. Also make sure your element is not inside iframe tag, it could cause problem as well.

Selenium two buttons with same xpath. Unable to click the one I need

There are two "EXPORT" buttons on the web page I am testing.
I am able to click the first using:
driver.find_element_by_xpath("//button[contains(.//text(),'EXPORT')]").click()
the driver then choses a dropdown and another div appears, again with an EXPORT button.
My code error when trying to execute:
driver.find_element_by_xpath("//button[contains(.//text(),'EXPORT')]").click()
for this element is:
selenium.common.exceptions.ElementClickInterceptedException: Message: element click intercepted: Element ... is not clickable at point (1824, 89). Other element would receive the click: ...
(Session info: chrome=92.0.4515.107)
So it says it is unable to click the first EXPORT button and the second one would get the click.
I've tried modifying my xpath expression to:
driver.find_element_by_xpath("//button[class()='MuiButtonBase-root MuiButton-root MuiButton-contained MuiButton-containedPrimary' and (.//text(),'EXPORT')]").click()
and a bunch of other attempts, but each time it is unable to locate. I want to be able to click the second EXPORT button (in the button class snippet shown in the pic).
You can differentiate between these two buttons with the help of xpath indexing.
Sample below :-
(//span[text()='EXPORT']/..)[1]
and for second button :-
(//span[text()='EXPORT']/..)[2]
and for this error
selenium.common.exceptions.ElementClickInterceptedException: Message:
element click intercepted: Element ... is not clickable at point
(1824, 89). Other element would receive the click: ... (Session info:
chrome=92.0.4515.107)
I would suggest you to open browser in full screen mode when it's launched.
driver.maximize_window()
or probably, you can use ActionChain as well :-
from selenium.webdriver.common.action_chains import ActionChains
ActionChains(driver).move_to_element(driver.find_element(By.XPATH, "(//span[text()='EXPORT']/..)[2]")).click().perform()
Update 1 :-
You can use find_elements as well to store all the web element and then try to click the one you want.
all_export_button = driver.find_elements(By.XPATH, "//span[text()='EXPORT']/..")
#to click on first
all_export_button[0].click()
#to click on Second
all_export_button[1].click()

'ElementNotVisibleException' Unable to click button with Selenium

A rather 'tricky' question that makes my head spin. I'm unable to click a button while using Selenium.
Css selector property: ValidateOrderForm > span > button
Xpath: #//*[#id="ValidateOrderForm"]/span/button
Attempts:
d.find_elements_by_xpath('ValidateOrderForm')[1].clear()
d.find_elements_by_id('ValidateOrderForm')[0].click()
d.find_element_by_css_selector("button.call-to-action").click()
And really everything in between.
Update: it gives the following error
ElementNotVisibleException: element not interactable

XPATH doesnt press a clickable button Python

my problem is that the first on is clicking and the second one doesnt and i dont undersatand why
WebDriverWait(rootdiv, 10).until(EC.element_to_be_clickable((By.XPATH, "//li[#onclick[contains(.,JTC)]]")))
rootdiv.find_element_by_xpath("//li[#onclick[contains(.,'JTC')]]").click()
WebDriverWait(depdiv, 10).until(EC.element_to_be_clickable((By.XPATH, "//li[#onclick[contains(.,AJU)]]")))
depdiv.find_element_by_xpath("//li[#onclick[contains(.,'AJU')]]").click()
depdiv and root div are children to look under for the certain li cause the root changes from the first to the second..
i've checked that the div is visible and in the first one, its clicking, the second time it cant find the object and im getting a time error
part of the code im trying to fed from..
<div class = "divCombo4">
<ul><li>....</li><ul>
<ul><li>...</li><ul>
</div>
and my depdiv is rooting to the find_element_by_id("divCombo4")
one of those ul li contains
onclick="selecionou('AJU', this,'.txtBusca4', 'false', 'destino', 'Estouem2', 'AJU');"
First of all, you need a dot to make the expressions context-specific. Also, the wait.until() returns a WebElement instance and you can use it instead of issuing a "find element" command again:
WebDriverWait(rootdiv, 10).until(EC.element_to_be_clickable((By.XPATH, ".//li[#onclick[contains(.,JTC)]]"))).click()
WebDriverWait(depdiv, 10).until(EC.element_to_be_clickable((By.XPATH, ".//li[#onclick[contains(.,AJU)]]"))).click()

Selenium (python): can't switch to iframe (name is dynamically generated)

I'm having problem selecting the iframe and accessing the different elements inside it. The iframe name is dynamically generated (e.g. frame11424758092173 or frame0005809321 or frame32138092173). The problem is that Selenium can't find the iframe no matter what i do....
switching to most recent frame doesn't work:
iframe = driver.find_elements_by_tag_name('iframe')[0]
driver.switch_to_frame(iframe)
Waiting for frame gets a timeout exception:
try:
iframe = WebDriverWait(driver, 5).until(EC.frame_to_be_available_and_switch_to_it(By.TAG_NAME('iframe')))
except:
logger.error(traceback.format_exc())
The following lines of code also times out:
try:
iframe = WebDriverWait(driver, 5).until(EC.presence_of_element_located((By.TAG_NAME, u"iframe")))
driver.switch_to_frame(iframe)
except:
logger.error(traceback.format_exc())
I have also tried iterating through the frames but it can't find it. The returned list is empty
iframes = driver.find_elements_by_tag_name('iframe')
#iframes is empty
really need some help...
Have you tried locating the iframe by its XPath and using the contains method?:
iframe = driver.find_element_by_xpath('//iframe[contains(#name, "frame")]')
driver.switch_to_frame(iframe)
Now you can access elements within the iframe.
To exit the iframe use:
driver.switch_to_default_content()
The contains method lets you get an element by a partial attribute value. Pretty useful for dynamically generated IDs, names, etc. You can search by other attributes as well using XPath. For example, say your iframe element has the attribute value = "3". You could use:
iframe = driver.find_element_by_xpath('//iframe[contains(#name, "frame")][#value = "3"]')
driver.switch_to_frame(iframe)
This approach can be used with any number of attributes as well.
You could also try getting the element by its selector. Keep in mind that this limits what you can do with it:
driver.execute_script('document.querySelector("INSERT SELECTOR HERE").doSomething();')
To get the Selector and/or XPath you're going to want to inpect the element using your browser (Chrome in my case). Right click on the element. Click Inspect. Then right click on the HTML element and click Copy > Copy Xpath or Copy > Copy Selector.
If that doesn't work for me, my last resort is to go the url of the iframe.To get that, you need to right-click on the area of the webpage where the iframe exists and click View Frame Source. It'll then lead you to a new page. The url of that page will be shown in the top of the browser after view-source:. You can then simply navigate to that url:
driver.get('insert url of iframe here')
And now you have access to the elements within the iframe. I do not recommend this approach if you are manipulating elements within the iframe and then exiting the iframe. Your changes will get lost. This will only work if you are scraping info off of that iframe, NOT if you are manipulating the elements within. Finding the iframe element and switching into it is usually better and safer.

Categories