如何访问 protonmail.com 上 iframe 内的消息字段?

问题描述 投票:0回答:1

我正在尝试在 Protonmail 服务器上使用 Python Selenium 发送电子邮件。一切正常,直到我收到电子邮件为止。

要访问电子邮件字段,我使用以下 xpath:

"//div[@id='rooster-editor']/div[1]"
。当通过 DOM 手动搜索时,它给出了一个唯一的元素(Chromium 也给出了相同的 xpath)。

但在脚本中,此 XPath 会引发“没有此类元素”异常。我首先认为该错误是由于页面未完全加载而引起的,如本文中所述:Selenium Webdriver - NoSuchElementExceptions。 为了避免这个问题,我插入了 20 秒

implicitly_wait
,但问题仍然存在。

我认为这个功能也不能解决问题:

EC.presence_of_element_located(By.XPATH,"//div[@id='rooster-editor']/div[1]"
因为我的代码片段比手动发送电子邮件慢。

总而言之,我在代码片段中引入了一些“等待”或“time.sleep”:从单击“新消息”按钮 -> 隐式等待 20 秒 -> 填写收件人电子邮件 -> 2 秒睡眠 -> 电子邮件主题 -> 3 秒睡眠 -> 然后发送电子邮件。因此,我认为问题可能不是由未完全加载的页面引起的。

所以我的问题是:什么会带来这样的异常?

from selenium import webdriver
from selenium.webdriver.common.by import By
import time

class FindProton():
        def test(self, recipient, subject, msg):
            self.recipient = recipient
            self.subject = subject
            self.msg = msg
            baseUrl = 'https://www.protonmail.com'
            driver = webdriver.Firefox()
            driver.get(baseUrl)
            driver.maximize_window()
            driver.implicitly_wait(5)
            time.sleep(2)
    
            #SIGN IN 
            elementXpath = driver.find_element(By.XPATH,"//span[text()='Sign in']") 
            elementXpath.click()
    
            #USERNAME 
            time.sleep(3)
            #elementId_0 = driver.find_element(By.ID,'username').click()
            elementId_0 = driver.find_element(By.ID,'username')
            #elementId_0.send_keys(self.user)
            elementId_0.send_keys('xxxxxxx')
    
            #PASSWORD
            time.sleep(1)
            elementId_1 = driver.find_element(By.ID,'password')
            #elementId_1.send_keys(self.passwd)
            elementId_1.send_keys('xxxxxx')
    
            time.sleep(2)
            elementId_2 = driver.find_element(By.XPATH,"//button[text()='Sign in']")
            elementId_2.click()
    
            #my router is the hell slow so I introduce a long implicit wait...
            driver.implicitly_wait(20)
            #time.sleep(1)
            elementId_3 = driver.find_element(By.XPATH,"//button[text()='New message']")
            elementId_3.click()
    
            driver.implicitly_wait(15)
            #recipient ; part of id=dynamic, so use id contains 
            element_4 = driver.find_element(By.XPATH,"//input[contains(@id,'to-composer-')]")
            element_4.send_keys(self.recipient)
    
            time.sleep(2)
            #subject, part of id = dynamic, so use id contains 
            element_5 = driver.find_element(By.XPATH,"//input[contains(@id,'subject-composer-')]")
            element_5.send_keys(self.subject)
               
            time.sleep(3)
            #email message: BUG HERE !
            element_6 = driver.find_element(By.XPATH,"//div[@id='rooster-editor']/div[1]").click()

    ff=FindProton()
    ff.test('unkn[email protected]','no subject email','this is a short message')
python selenium-webdriver nosuchelementexception
1个回答
1
投票

消息区域通过选择器

[data-testid=rooster-iframe]
放置在 iframe 中。

因此,要访问该元素,您需要先切换到 iframe 内容。

另请注意,该消息不是输入字段,要输入内容,您应该先单击它并模拟键盘操作。

在 iframe 中输入/任何其他操作后,要访问之前的上下文,您应该切换到默认上下文。

from selenium import webdriver
from selenium.webdriver import ActionChains
from selenium.webdriver.common.by import By
import time

   #your code
   action_chains = ActionChains(driver)
   message_frame = driver.find_element(By.CSS_SELECTOR, '[data-testid=rooster-iframe]')
   driver.switch_to.frame(message_frame)

   element_6 = driver.find_element(By.XPATH, "//div[@id='rooster-editor']/div[1]")
   element_6.click()
   action_chains.send_keys(msg).perform()
   # if you finished with actions inside iframe - add line below
   driver.switch_to.default_content()
© www.soinside.com 2019 - 2024. All rights reserved.