I have written a webscraping script that automatically logs into my Email account and sends a message.
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 = 'XXXXXXXXXXXXXX!'
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')
WebDriverWait(browser, 20).until(EC.frame_to_be_available_and_switch_to_it((By.CSS_SELECTOR, "iframe[title='Editor']")))
WebDriverWait(browser, 20).until(EC.element_to_be_clickable((By.CSS_SELECTOR, "div#squire"))).send_keys('Test message')
sendButton = WebDriverWait(browser, 10).until(EC.element_to_be_clickable((By.CSS_SELECTOR, "body > div.app-root > div.composer-container > div > div > div > footer > div > div.button-group.button-group-solid-norm.button-group-medium > button > span")))
sendButton.click()
browser.switch_to.default_content()
I wanted the browser to click the submit button after input of the message.
I have copied the CSS selector of the span element and tried this:
sendButton = WebDriverWait(browser, 10).until(EC.element_to_be_clickable((By.CSS_SELECTOR, "body > div.app-root > div.composer-container > div > div > div > footer > div > div.button-group.button-group-solid-norm.button-group-medium > button > span")))
sendButton.click()
I get the following error:
selenium.common.exceptions.NoSuchWindowException: Message: Browsing context has been discarded
I am not sure, if I targeted the right element for what I want to achieve. I often struggle to find the right strategy to target an element. What is the best way if there is no id element oder a nice and short css selector? I checked the Selenium docs (https://selenium-python.readthedocs.io/locating-elements.html) but hesitated choosing one of the suggested methods.
This is an HTML snipped fo the submit button:
<footer data-testid="composer:footer" class="composer-actions flex-item-noshrink flex max-w100">
<div class="flex flex-row-reverse flex-align-self-center w100 ml0-5 mr1-5 pl1-25 pr0-25 mb1">
<div class="button-group button-group-solid-norm button-group-medium" data-testid="composer:send-actions"><button class="button button-group-item button-ghost-weak composer-send-button" aria-busy="false" type="button" data-testid="composer:send-button" aria-describedby="tooltip-19621"><svg viewBox="0 0 16 16" class="icon-16p no-desktop no-tablet on-mobile-flex" role="img" focusable="false"><use xlink:href="#ic-paper-plane"></use></svg><span class="pl1 pr1 no-mobile">Senden</span></button></div>
<div
class="flex flex-item-fluid">
<div class="flex"><button class="button button-for-icon button-ghost-weak mr0-5" aria-busy="false" type="button" data-testid="composer:delete-draft-button" aria-describedby="tooltip-19622"><svg viewBox="0 0 16 16" class="icon-16p" role="img" focusable="false"><use xlink:href="#ic-trash"></use></svg><span class="sr-only">Entwurf löschen</span></button>
<button
class="button button-for-icon button-ghost-weak mr0-5" aria-busy="false" type="button" data-testid="composer:password-button" aria-pressed="false" aria-describedby="tooltip-19623"><svg viewBox="0 0 16 16" class="icon-16p" role="img" focusable="false"><use xlink:href="#ic-lock"></use></svg><span class="sr-only">Verschlüsselung</span></button><button aria-expanded="false" aria-busy="false" data-testid="dropdown-button" class="editor-toolbar-button interactive composer-toolbar-fontDropDown max-w100 flex flex-align-items-center flex-nowrap button button-for-icon composer-more-dropdown"
type="button" tabindex="-1" title="Weitere Optionen" aria-describedby="tooltip-19625"><svg viewBox="0 0 16 16" class="icon-16p" role="img" focusable="false"><use xlink:href="#ic-ellipsis"></use></svg><span class="sr-only">Weitere Optionen</span></button></div>
<div
class="flex-item-fluid flex pr1"><span class="mr0-5 mauto no-mobile color-weak">Nicht gespeichert</span>
<div class="composer-attachments-button-wrapper flex flex-flex-align-items-center"><label class="button button-for-icon button-ghost-weak inline-block text-center inline-flex" aria-busy="false" role="button" data-testid="composer:attachment-button" aria-describedby="tooltip-19626"><svg viewBox="0 0 16 16" class="icon-16p" role="img" focusable="false"><use xlink:href="#ic-paperclip"></use></svg><input type="file" multiple="" class="composer-attachments-button" data-testid="composer-attachments-button"></label></div>
</div>
</div>
</div>
</footer>