Having trouble locating an element with in an iframe using Selenium Python - python

I am attempting to click a button using an XPath but I am unable to locate the element. Complete noob here.
Here is the button element I copied:
<button _ngcontent-ygw-c218="" class="btn"><span _ngcontent-ygw-c218="" translate="">SHOW ALL</span></button>
Here is my programming:
ShowAll =driver.find_element_by_xpath('//*[#id="app-SelectComponents"]/div[1]/button[1]')
ShowAll.click()
I have tried the following solution I found online to no avail (I've also replaced the 'btn' with 'SHOW ALL', no luck there):
driver.switch_to.frame(driver.find_element_by_name('btn'))
ShowAll =driver.find_element_by_xpath('//*[#id="app-SelectComponents"]/div[1]/button[1]')
ShowAll.click()
driver.switch_to.default_content()
Much appreciated.
EDIT: Here is a picture for reference. What am I doing wrong or what I can do to work around this issue?

You need to add time to make sure the element is available before asking selenium to pick it.
Try this:
import time
driver.switch_to.frame(driver.find_element_by_name('btn'))
time.sleep(5) #you can change the 5 depending on the number that works
ShowAll =driver.find_element_by_xpath('//*[#id="app-SelectComponents"]/div[1]/button[1]').click()
driver.switch_to.default_content()

The element with the text as SHOW ALL is within an <iframe> so you have to:
Induce WebDriverWait for the desired frame to be available and switch to it.
Induce WebDriverWait for the desired element to be clickable.
You can use either of the following Locator Strategies:
Using CSS_SELECTOR:
WebDriverWait(driver, 20).until(EC.frame_to_be_available_and_switch_to_it((By.CSS_SELECTOR,"iframe#iParts")))
WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.CSS_SELECTOR, "button.btn > span[translate]"))).click()
Using XPATH:
WebDriverWait(driver, 20).until(EC.frame_to_be_available_and_switch_to_it((By.XPATH,"//iframe[#id='iParts']")))
WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.XPATH, "//button[#class='btn']/span[text()='SHOW ALL']"))).click()
Note : You have to add the following imports :
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
Reference
You can find a couple of relevant discussions in:
Ways to deal with #document under iframe
Switch to an iframe through Selenium and python
selenium.common.exceptions.NoSuchElementException: Message: no such element: Unable to locate element while trying to click Next button with selenium
selenium in python : NoSuchElementException: Message: no such element: Unable to locate element

Related

How to find and click the "Like" button on Facebook page using Selenium

I am trying to automate the process of liking pages on Facebook. I've got a list of each page's link and I want to open and like them one by one.
I think the Like button doesn't have any id or name, but it is in a span class.
<span class="x1lliihq x6ikm8r x10wlt62 x1n2onr6 xlyipyv xuxw1ft">Like</span>
I used this code to find and click on the "Like" button.
def likePages(links, driver):
for link in links:
driver.get(link)
time.sleep(3)
driver.find_element(By.LINK_TEXT, 'Like').click()
And I get the following error when I run the function:
selenium.common.exceptions.NoSuchElementException: Message: no such element: Unable to locate element
The classname attribute values like x1lliihq, x6ikm8r, etc, are dynamically generated and is bound to chage sooner/later. They may change next time you access the application afresh or even while next application startup. So can't be used in locators.
Moreover the the element is a <span> tag so you can't use By.LINK_TEXT
Solution
To click on the element Like you need to induce WebDriverWait for the element_to_be_clickable() and you can use either of the following locator strategies:
Using XPATH and text():
WebDriverWait(driver, 10).until(EC.element_to_be_clickable((By.XPATH, "//span[text()='Like']"))).click()
Using XPATH and contains():
WebDriverWait(driver, 10).until(EC.element_to_be_clickable((By.XPATH, "//*[contains(., 'Like')]"))).click()
Note: You have to add the following imports :
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
References
You can find a couple of relevant detailed discussions on NoSuchElementException in:
selenium.common.exceptions.NoSuchElementException: Message: no such element: Unable to locate element while trying to click Next button with selenium
selenium in python : NoSuchElementException: Message: no such element: Unable to locate element
You cannot use Link_Text locator as Like is not a hyperlink. Use XPath instead, see below:
XPath : //span[contains(text(),"Like")]
driver.find_element(By.XPATH, '//span[contains(text(),"Like")]').click()

Python Selenium can´t find a way to write in a form inside iframe tag

I'm trying to write some text to an element which looks like this:
The HTML code looks like this:
What I'am trying to do is to figure out, how it would be possible to send text in the form via Selenium.
I've tried alot of things but unfortinatly nothing works. Currently this is the code I have at the moment. I choose to use #class as an indicator of the frame as this value doesn´t change everytime the website reloads.
iframeDescription = driver.find_element_by_xpath("//iframe[#class='ifrm']")
driver.switch_to.frame(iframeDescription)
time.sleep(2)
print(iframeDescription)
formInput = driver.find_element(By.CSS_SELECTOR, "html")
formInput.send_keys("a random Text I wish would appear inside this Box")
I would appreciate some advice.
Edit: thanks for the quick answers guys, I don´t have input tho- or am I missing something? I´ve wrote "test" into the form on the website to try and locate it.
Pic3
The element is within an <iframe> so you have to:
Induce WebDriverWait for the desired frame to be available and switch to it.
Induce WebDriverWait for the desired element to be clickable.
Note: You can't send a character sequence to the body tag, instead you have to locate the relevant <input> tag to send the text.
You can use either of the following Locator Strategies:
Using CSS_SELECTOR:
WebDriverWait(driver, 20).until(EC.frame_to_be_available_and_switch_to_it((By.CSS_SELECTOR,"iframe[title='Standard']")))
WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.CSS_SELECTOR, "body input"))).send_keys("Sawa")
Using XPATH:
WebDriverWait(driver, 20).until(EC.frame_to_be_available_and_switch_to_it((By.XPATH,"//iframe[#title='Standard']")))
WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.XPATH, "//body//input"))).send_keys("Sawa")
Note : You have to add the following imports :
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
Reference
You can find a couple of relevant discussions in:
Switch to an iframe through Selenium and python
selenium.common.exceptions.NoSuchElementException: Message: no such element: Unable to locate element while trying to click Next button with selenium
selenium in python : NoSuchElementException: Message: no such element: Unable to locate element

How to change between iframes in Selenium and Python

I was trying to understand how to change between iframes in selenium webdriver, but I could not figure it out.
In the image ahead, is the iframe that I want to switch to:
Snapshot:
//iframe[#class='viewer pbi-frame']
Should be a simple xpath using driver.switch_to.frame()
Or
//iframe[#title='Power BI Report Viewer']
In order to switch to the iframe you can use code like this:
driver.switch_to.frame(driver.find_element_by_css_selector("//iframe[#title='PowerBi Report Viewer']"))
When finished working inside the iframe you will have to switch back to the default content with
driver.switch_to.default_content()
The website is Power BI based, so to switch within the <iframe> so you have to:
Induce WebDriverWait for the desired frame to be available and switch to it.
You can use either of the following Locator Strategies:
Using CSS_SELECTOR:
WebDriverWait(driver, 20).until(EC.frame_to_be_available_and_switch_to_it((By.CSS_SELECTOR,"iframe[title='PowerBi Report Viewer']")))
Using XPATH:
WebDriverWait(driver, 20).until(EC.frame_to_be_available_and_switch_to_it((By.XPATH,"//iframe[#title='PowerBi Report Viewer']")))
Note : You have to add the following imports :
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
Reference
You can find a couple of relevant discussions in:
Switch to an iframe through Selenium and python
selenium.common.exceptions.NoSuchElementException: Message: no such element: Unable to locate element while trying to click Next button with selenium
selenium in python : NoSuchElementException: Message: no such element: Unable to locate element

Python and Selenium: Locating and clicking a button for cookies within an iframe

Anybody has a solution to locate a button in webpage with an overlayed popup window like in the following example:
from selenium import webdriver
driver = webdriver.Firefox(executable_path=r'./geckodriver')
driver.get("https://www.academics.de/")
#after waiting for a while the popup window comes up
driver.find_elements_by_xpath("//*[contains(text(), 'Zustimmen')]")
The returned list is empty. Running the following
driver.find_element_by_css_selector(".button-accept")
results in:
NoSuchElementException: Message: Unable to locate element: .button-accept
The element with the text as E-Mail Login is within an iframe so you have to:
Induce WebDriverWait for the desired frame to be available and switch to it.
Induce WebDriverWait for the desired element to be clickable.
You can use either of the following Locator Strategies:
Using CSS_SELECTOR:
driver.get("https://www.academics.de/")
WebDriverWait(driver, 20).until(EC.frame_to_be_available_and_switch_to_it((By.CSS_SELECTOR,"iframe[title='SP Consent Message']")))
WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.CSS_SELECTOR, "button[title='Zustimmen']"))).click()
Using XPATH:
driver.get("https://www.academics.de/")
WebDriverWait(driver, 20).until(EC.frame_to_be_available_and_switch_to_it((By.XPATH,"//iframe[#title='SP Consent Message']")))
WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.XPATH, "//button[#title='Zustimmen']"))).click()
Note : You have to add the following imports :
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
Reference
You can find a couple of relevant discussions in:
Switch to an iframe through Selenium and python
selenium.common.exceptions.NoSuchElementException: Message: no such element: Unable to locate element while trying to click Next button with selenium
selenium in python : NoSuchElementException: Message: no such element: Unable to locate element
An easy workaround to your problem would be to use uBlock Origin extension + Fanboy's Annoyances blocklist on your Selenium instance so that these annoying cookies messages would outright never appear. A way of enabling extensions is described in this StackOverflow answer:
Create a new firefox profile via right click windows start button >
run > firefox.exe -P
Then add whatever extensions you want, ublock, adblock plus etc
Call your profile folder with
profile = selenium.webdriver.FirefoxProfile("C:/test")
browser = selenium.webdriver.Firefox(firefox_profile=profile, options=ops)

Click on ember.js enabled element using Selenium

I am trying to click on the following button on a linkedin page using selenium:
<button id="ember607" class="share-actions__primary-action artdeco-button artdeco-button--2 artdeco-button--primary ember-view" data-control-name="share.post"><!---->
<span class="artdeco-button__text">
Post
</span></button>
I have tried to use:
driver.find_element_by_id, but the id of the button seems to keep changing number
driver.find_element_by_xpath, but this contains the button number, so also fails
driver.find_element_by_class_name('share-actions__primary-action artdeco-button artdeco-button--2 artdeco-button--primary ember-view'), this fails even though the class name is correct ?
Basically, all methods generate the same error message:
Exception has occurred: NoSuchElementException
Message: no such element: Unable to locate element:{[*the_error_is_here*]}
I have also tried the xpath contains() method, but this does not find the button.
What would be the correct way to click on this button please ?
I am using python version 3.9 on windows with driver = webdriver.Chrome
The element is an Ember.js enabled element. So to click() on the element with text as Post you can use either of the following Locator Strategies:
Using css_selector:
driver.find_element_by_css_selector("button.share-actions__primary-action[data-control-name='share.post']>span.artdeco-button__text").click()
Using xpath:
driver.find_element_by_xpath("//button[contains(#class, 'share-actions__primary-action') and #data-control-name='share.post']/span[#class='artdeco-button__text' and contains(., 'Post')]").click()
Ideally, to click on the element you need to induce WebDriverWait for the element_to_be_clickable() and you can use either of the following Locator Strategies:
Using CSS_SELECTOR:
WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.CSS_SELECTOR, "button.share-actions__primary-action[data-control-name='share.post']>span.artdeco-button__text"))).click()
Using XPATH:
WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.XPATH, "//button[contains(#class, 'share-actions__primary-action') and #data-control-name='share.post']/span[contains(., 'Post')]"))).click()
Note: You have to add the following imports :
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
References
You can find a couple of relevant detailed discussions in:
Selenium - Finding element based on ember
Automate Ember.js application using Selenium when object properties are changed at run-time
Ember: Best practices with Selenium to make integration tests in browser
Ember dropdown selenium xpath
Sometimes there are problems with buttons that are not clickable at the moment.
Try this:
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.common.by import By
wait = WebDriverWait(driver, 10)
button = wait.until(EC.element_to_be_clickable((By.XPATH, '[YOUR X_PATH TO THE BUTTON]')))
driver.execute_script("arguments[0].click()", button)
It's not the cleanest way to click any Button with selenium, but for me this method works mostly everytime.
//button[#class="share-actions__primary-action artdeco-button artdeco-button--2 artdeco-button--primary ember-view"].
Or
//button[contains(#id,'ember')]
Find the span with Post and click it's button tag.
//span[contains(text(), 'Post')]/parent::button
By xpath this should work:
//button/span[contains(text(), "Post")]
Combine it with a wait for the element:
button = WebDriverWait(driver, 10).until(
EC.element_to_be_clickable((By.XPATH, "//button/span[contains(text(), "Post")]"))
)
The problem with your by class selectors is the multiple class names. See this question: How to get elements with multiple classes for more details on how to overcome that.

Categories