How can I select a html element no matter what frame it is in in selenium?
No, it is not possible to interact with any WebElement within an <iframe>
through Selenium without switching to the respective iframe
.
Reason :
When a page is loaded, Selenium's focus by default remains on the Top Window. The Top Window contains the other <iframes>
and the framesets. So when we need to interact with a WebElement which is within an iframe we have to switch to the respective <iframe>
through one of the below-mentioned methods :
Frame Switching Methods :
We can switch over to frames by 3 ways.
By Frame Name :
Name attribute of iframe through which we can switch to it.
Example:
driver.switch_to.frame("iframe_name")
By Frame ID :
ID attribute of iframe through which we can switch to it.
Example:
driver.switch_to.frame("iframe_id")
By Frame Index :
Suppose if there are 10 frames in the page, we can switch to the iframe by using the index.
Example:
driver.switch_to.frame(0)
driver.switch_to.frame(1)
Switching back to the Main Frame :
We can switch back to the main frame by using default_content()
or parent_frame()
Example:
driver.switch_to.default_content()
driver.switch_to.parent_frame()
A Better Approach to Switch Frames:
A better way to switch frames will be to induce WebDriverWait
for the availability of the intended frame with expected_conditions
set to frame_to_be_available_and_switch_to_it
as follows :
Through Frame ID:
WebDriverWait(driver, 10).until(EC.frame_to_be_available_and_switch_to_it(By.ID,"id_of_iframe"))
Through Frame Name:
WebDriverWait(driver, 10).until(EC.frame_to_be_available_and_switch_to_it((By.NAME,"name_of_iframe")))
Through Frame Xpath:
WebDriverWait(driver, 10).until(EC.frame_to_be_available_and_switch_to_it((By.XPATH,"xpath_of_iframe")))
Through Frame CSS:
WebDriverWait(driver, 10).until(EC.frame_to_be_available_and_switch_to_it((By.CSS_SELECTOR,"css_of_iframe")))
Reference
You can find a relevant detailed discussion in:
- Ways to deal with #document under iframe
How to locate an element inside this iframe with selenium?
As the element is within an <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='To Do Assignments in Connect'][src='https://connect.mheducation.com/paamweb/index.html#/access/home']")))
Using XPATH:
WebDriverWait(driver, 20).until(EC.frame_to_be_available_and_switch_to_it((By.XPATH,"//iframe[@title='To Do Assignments in Connect' and @src='https://connect.mheducation.com/paamweb/index.html#/access/home']")))
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:
- How can I select a html element no matter what frame it is in in selenium?
Identifying element from nested HTML code under frame using Selenium (confirmed no iframe)
The <input>
tag with id
as testFormNumForLastAttempt seems to be nested within 3 layers of <frame>
.
So to click()
within the element you have to:
- Ignore (safely) the presence of parent or child
<frameset>
tags. - Induce WebDriverWait for the first layer of
frame_to_be_available_and_switch_to_it()
. - Induce WebDriverWait for the second layer of _
frame_to_be_available_and_switch_to_it()
. - Induce WebDriverWait for the third layer of
frame_to_be_available_and_switch_to_it()
. - Induce WebDriverWait for the desired
element_to_be_clickable()
. You can use the following solution:
Code Block:
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
WebDriverWait(driver, 10).until(EC.frame_to_be_available_and_switch_to_it((By.NAME,"applet_container")))
WebDriverWait(driver, 10).until(EC.frame_to_be_available_and_switch_to_it((By.CSS_SELECTOR,"frame[name='javascript_container'][src$='__AUTHENTICATION_REQUEST_PARAMETER_MECHANISM__=applet']")))
WebDriverWait(driver, 10).until(EC.frame_to_be_available_and_switch_to_it((By.XPATH,"//frame[@name='main' and contains(@src, 'Loading')]")))
WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.CSS_SELECTOR, "input#testFormNumForLastAttempt[name='testFormNumForLastAttempt']"))).click()
You can find a relevant discussion in How to locate and click on an element which is nested within multiple frame and frameset through Selenium using Webdriver and C#
Outro
- How can I select a html element no matter what frame it is in in selenium?
- Ways to deal with #document under iframe
How do I Switch to Iframe and enter text in field with Selenium
The iframe
has a class-name - webAuthContainer__iframe
. Can make use of the same to switch to the iframe
.
please = driver.find_element_by_css_selector('button.frontHero__loginButton')
please.click()
# Switch to iframe using class-name
wait.until(EC.frame_to_be_available_and_switch_to_it((By.CLASS_NAME,"webAuthContainer__iframe")))
attempt = wait.until(EC.element_to_be_clickable((By.ID,"sign_in_up_email")))
attempt.send_keys("example@email.com")
# Switch to default content to interact with elements outside the iframe
driver.switch_to.default_content()
Selenium unable to locate my elements(buttons)
When you have clicked on the iframe and you need to come back to the prev frame or the default frame, you should use driver.switch_to.default_content()
and then you can click on the button on the default content.
This would switch the context to the default frame and you would be able to again operate on it.
Python Selenium: how to switch frames after navigation?
selenium.common.exceptions.NoSuchFrameException: Message: contents
this is because you are staying in child level of iframe which is 'menu' so inside that it can't able to find the iframe 'contents'.
First Switch back to the parent frame which is "contents", by using
DRIVER.switch_to.default_content()
and then try to go to the 'contents' iframe and perform actions, Now it should work.
Related Topics
How to Make a Sprite Move When Key Is Held Down
How to Make a Dictionary from Separate Lists of Keys and Values
Difference Between Python'S List Methods Append and Extend
Pygame Mouse Clicking Detection
What Is the Maximum Recursion Depth in Python, and How to Increase It
How to Get Keyboard Input in Pygame
Why Doesn't Calling a String Method Do Anything Unless Its Output Is Assigned
How to Group Dataframe Rows into List in Pandas Groupby
Tkinter Assign Button Command in a For Loop With Lambda
I'M Getting an Indentationerror. How to Fix It
Limiting Floats to Two Decimal Points
Error: Unable to Find Vcvarsall.Bat
Fastest Way to List All Primes Below N
Why Is the Output of My Function Printing Out "None"
How to Parse Xml and Get Instances of a Particular Node Attribute