简体   繁体   中英

How can I access the input field within an iframe using Selenium and Python

I am writing a webscraping script that automatically logs into my Email account and sends a message.

I have written the code to the point where the browser has to input the message. I don't know how to access the input field correctly. I have seen that it is an iframe element. Do I have to use the.switch_to_frame() method and how can I do that? How can I switch to the iframe if there is no name attribute? Do I need the switch_to_frame() method or can I just use the find_element_by_css_selector() method?

This is the source code of the iframe:

在此处输入图像描述

Here is my code:

from selenium import webdriver
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC

myPassword = 'xxxxxxxxxxxxxxxx'

browser = webdriver.Firefox() # Opens Firefox webbrowser
browser.get('https://protonmail.com/') # Go to protonmail website
loginButton = WebDriverWait(browser, 10).until(EC.presence_of_element_located((By.CSS_SELECTOR, "a.btn-ghost:nth-child(1)")))
loginButton.click()
usernameElem = WebDriverWait(browser, 10).until(EC.element_to_be_clickable((By.CSS_SELECTOR, "#username")))
usernameElem.send_keys("first.last@protonmail.com")
passwordElem = browser.find_element_by_css_selector("#password")
passwordElem.send_keys(myPassword)
anmeldenButton = browser.find_element_by_css_selector(".button")
anmeldenButton.click()
newMessage = WebDriverWait(browser, 10).until(EC.element_to_be_clickable((By.XPATH, "/html/body/div[1]/div[3]/div/div/div[1]/div[2]/button")))
newMessage.click()
addressElem = WebDriverWait(browser, 10).until(EC.element_to_be_clickable((By.CSS_SELECTOR, "input[id^='to-composer']")))
addressElem.send_keys('first.last@mail.com')
subjectElem = WebDriverWait(browser, 10).until(EC.element_to_be_clickable((By.CSS_SELECTOR, "input[id^='subject-composer']")))
subjectElem.send_keys('anySubject')
messageElem = WebDriverWait(browser, 10).until(EC.element_to_be_clickable((By.CSS_SELECTOR, "#squire > div > div:nth-child(1)")))
messageElem.send_keys('message')

To access the <input> field within the <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[title='Editor']"))) WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.CSS_SELECTOR, "element_css"))).click()
    • Using XPATH :

       WebDriverWait(driver, 20).until(EC.frame_to_be_available_and_switch_to_it((By.XPATH,"//iframe[@title='Editor']"))) WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.XPATH, "element_xpath"))).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:

You have to switch to iframe with driver.switch_to.frame method.
Like any other web element iframe element can be located by ID , CLASS , XPATH , CSS_SELECTOR etc.
Looks like here you can use this method:

WebDriverWait(driver, 10).until(EC.frame_to_be_available_and_switch_to_it((By.CSS_SELECTOR,"iframe[title='Editor']")))

Or

WebDriverWait(driver, 10).until(EC.frame_to_be_available_and_switch_to_it((By.CSS_SELECTOR,"iframe[data-testid='squire-iframe']")))

When finished working within the iframe you will have to switch back to the default content with

driver.switch_to.default_content()

you first need to switch to iframe

wait = WebDriverWait(driver, 30)
wait.until(EC.frame_to_be_available_and_switch_to_it((By.CSS_SELECTOR, "iframe[title='Editor']")))

and now here write the code to send the message body. something like this:

email = wait.until(EC.visibility_of_element_located((By.CSS_SELECTOR, "div#squire div>div")))
driver.execute_script("arguments[0].setAttribute('value', 'email body')", email)

also once you are done with iframe interaction, you should switch to default content:

driver.switch_to.default_content()

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM