如何使用 Selenium 和 Python 在 iframe 中使用 contenteditable="true" 在输入字段中发送文本

How to send text within an input field with contenteditable="true" within an iframe using Selenium and Python

我正在编写一个自动登录到我的电子邮件帐户并发送消息的网络抓取脚本。

我已经把代码写到浏览器必须输入消息的地步了。我不知道如何正确访问输入字段。我已经看到它是一个 iframe 元素。我必须使用 switch_to_frame() 方法吗?我该怎么做?如果没有 name 属性,如何切换到 iframe?我需要 switch_to_frame() 方法还是只使用 find_element_by_css_selector() 方法?

这是 iframe 的源代码:

这是我的代码:

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')

要访问 中的 <input> 字段,您必须:

  • 诱导 WebDriverWait 所需的 帧可用并切换到它

  • 诱导 所需的 元素可点击

  • 您可以使用以下任一项:

    • 使用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, "div#squire"))).send_keys('message')
      
    • 使用 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, "//div[@id='squire']"))).send_keys('message')
      
  • 注意:您必须添加以下导入:

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

PS: As the <div> tag is having the attribute you can still send text to the element.


参考

您可以在以下位置找到一些相关讨论:

  • Switch to an iframe through Selenium and python

您必须使用 driver.switch_to.frame 方法切换到 iframe。
与任何其他 Web 元素一样,iframe 元素可以通过 IDCLASSXPATHCSS_SELECTOR
定位 看起来在这里你可以使用这个方法:

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

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

在 iframe 中完成工作后,您必须使用

切换回默认内容
driver.switch_to.default_content()

您首先需要切换到 iframe

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

现在在这里编写发送消息正文的代码。像这样:

wait.until(EC.frame_to_be_available_and_switch_to_it((By.CSS_SELECTOR, "iframe[title='Editor']")))
wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR, "div#squire"))).click()

email = wait.until(EC.visibility_of_element_located((By.CSS_SELECTOR, "div#squire div:nth-child(2)")))
email.send_keys('write the email here')

另外,一旦您完成了 iframe 交互,您应该切换到默认内容:

driver.switch_to.default_content()