I am very new to Selenium and am trying to automate sending messages through WhatsApp Web through Google Chrome. I am using a different api which lets users write messages directly to the phone number specified: https://wa.me/. However, there is an alert box which pops up and my code is unable to accept it.
Alert box screenshot
I have tried
driver.switch_to_alert().accept()
but this is resulted in a deprecation warning, so switched to:
alert_box = driver.switch_to.alert
alert_box.accept()
Both result in the following error:
Exception has occurred: NoAlertPresentException
Message: no such alert
(Session info: chrome=105.0.5195.102)
File "<hidden>", line 30, in <module>
driver.switch_to.alert.accept()
Current code:
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
PATH = "C:\Program Files (x86)\chromedriver.exe"
driver = webdriver.Chrome(PATH)
# Ensure you are logged in to whatsapp web
num = "xxxxxxxxxxxxxxxxxxxxx" # hid the number
driver.get("https://wa.me/" + num)
# Allow time to load page
driver.implicitly_wait(3)
# Switch to alert window to accept the alert to open URL
driver.switch_to.alert.accept()
driver.find_element(By.XPATH, './/a[#class="_9vcv _advm _9scb"][#id="action-button"][#title="Share on WhatsApp"]').click()
# Switch to alert window to accept the alert to open URL
driver.switch_to_alert().accept()
driver.find_element(By.XPATH, '//*[#id="fallback_block"]/div/div/h4[2]/a').click()
Interestingly, no alert shows up if I manually go through the screens myself.
Thanks in advance!
You probably should add some code to wait for the alert to open.
Have a look a the following snipped.
from selenium import webdriver
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.common.exceptions import TimeoutException
try:
wait = WebDriverWait(driver, 10)
wait.until(EC.alert_is_present(), 'waiting for alert')
alert = driver.switch_to.alert
alert.accept()
except TimeoutException:
print("timed out waiting for alert")
Related
I am trying to download the data from https://projects.propublica.org/nonprofits for my research. When the page is open, a notification window pops up. I tried to use python selenium to close it. My code is as follows,
from selenium.webdriver import Chrome
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
driver = Chrome()
driver.get('https://projects.propublica.org/nonprofits')
driver.find_element(By.XPATH, "/html/body/div[1]/div/div[2]/p[2]/a").click()
I got the error message: selenium.common.exceptions.NoSuchElementException: Message: no such element: Unable to locate element: {"method":"xpath","selector":"/html/body/div[1]/div/div[2]/p[2]/a"}
(Session info: chrome=99.0.4844.51)
I revised my code as
driver.get('https://projects.propublica.org/nonprofits')
WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.XPATH, "/html/body/div[1]/div/div[2]/button"))).click()
The error message is TimeoutException(message, screen, stacktrace)
selenium.common.exceptions.TimeoutException: Message:
Stacktrace:
Backtrace:
Ordinal0 [0x005E9943+2595139]
...
Any suggestion to overpass the notification windows is highly appreciated. Thank you.
The element you are trying to click is inside an iframe - you have to switch to that iframe first in order to access this element
You have to add waits to let the elements be loaded before accessing them.
This will work better:
from selenium.webdriver import Chrome
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
driver = Chrome()
driver.get('https://projects.propublica.org/nonprofits')
wait = WebDriverWait(driver, 20)
wait.until(EC.frame_to_be_available_and_switch_to_it((By.CSS_SELECTOR,"iframe.syndicated-modal")))
wait.until(EC.visibility_of_element_located((By.XPATH, "//a[contains(#href,'newsletter-roadblock')]"))).click()
When finished working inside the iframe you will need to switch to the default content with
driver.switch_to.default_content()
I am trying to create a bot that clicks on a link on my site, opens a tab, closes, and then continues the cycle.
This keeps getting hungup after the 4-5 cycle however.
I also cannot figure out how to simply close both of the tabs, and get the url again as to not have to quit.
Sorry if this is very basic, I am new to this. :)
I am using selenium, firefox webdriver
from time import sleep
from selenium import webdriver
from keyboard import press
while True:
browser = webdriver.Firefox()
browser.implicitly_wait(10)
browser.get('https://pridedogecoin.com/')
sleep(15)
login_link = browser.find_element_by_xpath('//*[#id="slider-6-slide-6-layer-13"]')
login_link.click()
sleep(5)
browser.quit()
sleep(15)
okay, you need to switch to first tab like below, also you should use close not quit, since close is meant to kill current window instance, where as quit will kill all of the browser instance :
import time
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
from selenium.webdriver.common.action_chains import ActionChains
driver = webdriver.Firefox(executable_path = "D:\geckodriver.exe")
driver.maximize_window()
while True:
driver.refresh()
time.sleep(10)
driver.get("https://pridedogecoin.com/")
driver.implicitly_wait(60)
wait = WebDriverWait(driver, 30)
current_windows_handle = driver.current_window_handle
wait.until(EC.element_to_be_clickable((By.ID, "slider-6-slide-6-layer-13"))).click()
driver.switch_to.window(driver.window_handles[1])
time.sleep(5)
driver.close()
driver.switch_to.window(current_windows_handle)
I am trying to automate saving website's description and url. I loop the program and come to the function get_info(). Basically it need to add the first website on the google page I load and scroll down so when it executes again it can add other websites. The problem is that the program refresh the page everytime it executes get_info() and brings you back at the top.
import selenium
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.common.exceptions import TimeoutException
import time
browser=webdriver.Firefox()
def get_info():
browser.switch_to.window(browser.window_handles[2])
description = WebDriverWait(browser, 10).until(
EC.presence_of_element_located((By.TAG_NAME, "h3"))
).text
site = WebDriverWait(browser, 10).until(
EC.presence_of_element_located((By.TAG_NAME, "cite"))
)
site.click()
url=browser.current_url
browser.back()
browser.execute_script("window.scrollBy(0,400)","")
To stop Chrome from auto-reloading , you can do this
driver.execute_cdp_cmd('Emulation.setScriptExecutionDisabled', {'value': True})
Link to read about this Chrome Devtools flag - here
The question already has been asked here
I tried to login to https://einvoice1.gst.gov.in/ with selenium but it is not acting consistently, 80% of the time it fails with 400 error even after using wait of up-to 4 sec after every action.
browser = webdriver.Chrome(PATH,options = options)
browser.set_window_size(1900, 1200)
browser.implicitly_wait(4)
browser.get('https://einvoice1.gst.gov.in')
browser.find_element_by_id('btnLogin').click() # opening login window (same page)
browser.find_element_by_id('txtUserName').send_keys(username)
browser.find_element_by_id('txt_password').send_keys(password)
# waiting for few seconds to enter Captcha
browser.find_elements_by_tag_name('button')[2].click() # submit form
Response:
HTTP Error 400
Apply waits on elements and click on login prior to entering. There is a captchacode I don't know how to handle. You might need to input for that.
WebDriverWait(browser, 10).until(EC.element_to_be_clickable((By.ID, "btnLogin"))).click()
WebDriverWait(browser, 10).until(EC.element_to_be_clickable((By.ID, "txtUserName"))).send_keys(username)
WebDriverWait(browser, 10).until(EC.element_to_be_clickable((By.ID, "txt_password"))).send_keys(password)
WebDriverWait(browser, 10).until(EC.element_to_be_clickable((By.NAME, "CaptchaCode"))).send_keys('5')
WebDriverWait(browser, 10).until(EC.element_to_be_clickable((By.NAME,"LoginButton"))).click()
Import
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
There are many solutions for interaction with alerts in web pages using Selenium in Python. But, I want a solution to find that the page has an alert or no. Use of Try & except is very bad solution in my case. So, don't present that. I want just a simple if & else solution.
This is my solution:
if driver.switch_to_alert()
alert = driver.switch_to_alert()
alert.accept()
else:
print('hello')
NoAlertPresentException: no such alert
(Session info: chrome=73.0.3683.103)
(Driver info: chromedriver=2.46.628402 (536cd7adbad73a3783fdc2cab92ab2ba7ec361e1),platform=Windows NT 10.0.16299 x86_64)
You can do:
driver.executeScript("window.alert = () => window.alertHappened = true")
// some code here that may cause alert
alert_happened = driver.executeScript("return !!window.alertHappened")
When you automate the Regression Testcases you are always aware that where there is an alert on the webpage. As per the current implementation to switch to an Alert you need to use:
switch_to.alert() as follows:
selenium.webdriver.common.alert
driver.switch_to.alert().accept()
As per best practices you should always induce WebDriverWait for the alert_is_present() while switching to an Alert as follows:
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
# other lines of code
WebDriverWait(driver, 5).until(EC.alert_is_present).accept()
To validate that a page has an Alert or not the ideal approach would be to wrap up the Alert handling code block in a try-catch{} block as follows:
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
from selenium.common.exceptions import TimeoutException
try:
WebDriverWait(driver, 5).until(EC.alert_is_present).accept()
print("Alert accepted")
except TimeoutException:
print("No Alert was present")
Reference
You can find a couple of relevant discussion in:
How to read the text from the alert box using Python + Selenium
Why switching to alert through selenium is not stable?
Outro
There may be some cases when you may need to interact with elements those cannot be inspected through css/xpath within google-chrome-devtools and you will find a detailed discussion in How to interact with elements those cannot be inspected through css/xpath within google-chrome-devtools