我正在尝试在 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')
谢谢大家!
消息区域通过选择器
[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()