I can't figure out how to get around this in Python. The email pop-up is preventing Selenium from clicking on one of the footer links because the pop-up blocks the view of it. I ideally would like to click the "X" and not enter an email.
I've tried using what was in the Selenium documentation about prompts but none of it worked or perhaps I implemented it incorrectly. I tried some of what I already found in stack overflow, which you can see in the commented out code, but kept getting all kinds of errors.
import requests
from urllib.parse import urljoin
from bs4 import BeautifulSoup
from urllib.request import urlopen as uReq
from selenium.webdriver.support.ui import WebDriverWait
from selenium import webdriver
from selenium.webdriver.support import ui
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys
url = "https://www.standardmedia.co.ke/"
driver = webdriver.Chrome()
driver.get(url)
html = driver.page_source.encode('utf-8')
page_num = 0
##options = Firefox_options();
##options.addPreference("dom.disable_beforeunload", true)
##driver = webdriver.Firefox(options);
#click on the headings in the footer
for i in range (0,1):
footer = driver.find_elements_by_css_selector('#top-footer li')[i]
## if(driver.switch_to.alert != null):
## alert = driver.switch_to.alert
## alert.dismiss()
try:
WebDriverWait(driver, 10).until(EC.alert_is_present())
alert = driver.switch_to_alert()
alert.dismiss()
print("Alert dismissed.")
except TimeoutException:
print("No alert.")
footer.click()
print("alert dismissed")
page_num += 1
subheadings = driver.find_elements_by_css_selector('.title a')
len(subheadings)
The most recent error for a Firefox web driver was "No connection could be made because the target machine actively refused it."
WebDriver Alert class is designed to work with JavaScript Alerts to wit:
Window.alert()
Window.confirm()
Window.prompt()
At the page you're trying to test this modal popup is a normal <div>
therefore you will not be able to use Alert class, you will have to normally locate close button using find_element() function and click it.
Open the page:
driver.get("https://www.standardmedia.co.ke/")
Wait for the popup to appear
popup = WebDriverWait(driver, 10).until(expected_conditions.presence_of_element_located((By.CLASS_NAME, "mc-closeModal")))
Click the close button
popup.click()
Aside from the selenium connection issue, to address the main question, it looks like you are not calling the switch_to_alert function. Once you get selenium connecting, try the following:
alert = driver.switch_to_alert()
alert.dismiss()
Also note, your wait times are in seconds which seem pretty high/long in your code.
Related
Ive been attempting to use selenium to go through elements on soundclouds website and am having trouble interacting with the input tags. When I try to write in the input tag of the class "headerSearch__input" with the send keys command, I get back the error "Message: element not interactable". May someone please explain to me what im doing wrong?
from tkinter import *
import random
import urllib.request
from bs4 import BeautifulSoup
from selenium import webdriver
import time
import requests
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.chrome.options import Options
driver = webdriver.Chrome(executable_path='/Users/quanahbennett/PycharmProjects/SeleniumTest/chromedriver')
url= "https://soundcloud.com/"
driver.get(url)
#time.sleep(30)
wait = WebDriverWait(driver, 30)
#link = driver.find_elements_by_link_text("Sign in")
#link[0].click()
#driver.execute_script("arguments[0].click();", link[0])
#SUCCESFUL LOGIN BUTTON PUSH
#please = driver.find_element_by_css_selector('button.frontHero__loginButton')
#please.click()
attempt = driver.find_element_by_css_selector('input.headerSearch__input')
time.sleep(10)
attempt.send_keys('Hello')
breakpoint()
#driver.quit()
The locator - input.headerSearch__input is highlighting two different elements in the DOM. Its important to find unique locators. Link to refer
And also close the cookie pop-up. And then try to interact with elements.
Try like below and confirm.
driver.get("https://soundcloud.com/")
wait = WebDriverWait(driver,30)
# Click on Accept cookies button
wait.until(EC.element_to_be_clickable((By.ID,"onetrust-accept-btn-handler"))).click()
search_field = wait.until(EC.element_to_be_clickable((By.XPATH,"//div[#id='content']//input")))
search_field.send_keys("Sample text")
I am experimenting with Selenium and I have a code that load some URL and click on the button, so far my code looks like this:
import time
from selenium import webdriver
driver = webdriver.Chrome()
url = "https://example.org/"
driver.get(url)
button = driver.find_element_by_class_name("cool-button")
button.click()
driver.quit()
This code works as expected, but what am trying to achieve is this:
when this script finished it should start again, and again, let's say like infinite loop, so click on the button, close, open URL again, close, and so on:
I am new to Python and I try something like this:
import time
from selenium import webdriver
while True:
driver = webdriver.Chrome()
url = "https://example.org/"
driver.get(url)
button = driver.find_element_by_class_name("cool-button")
button.click()
driver.quit()
Can anybody try to help me with this?
We do the same thing here where we test when we want to attempt a "retry" of a test. One thing to note in your code above; you give no wait time for the "cool-button" to appear, become clickable or it's presence known; that will often lead to a failing result. I added support for that; as well as encompassed the entire code in an keyboard interrupted while loop.
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
import time
try:
while True:
driver = webdriver.Chrome()
url = "https://example.org/"
driver.get(url)
try:
button = WebDriverWait(driver, 5).until(EC.presence_of_element_located((By.CLASS_NAME, "cool-button")))
button.click()
except:
print('could not find the "cool" button')
pass
driver.quit()
print("Press CTRL+C to escape!")
time.sleep(3)
except KeyboardInterrupt:
quit()
I'd also suggest this youtube as a very good resource on the topic of selenium:
https://www.youtube.com/watch?v=b5jt2bhSeXs
I'm working on a online purchase bot for target.com and I've run into a blocker. Upon providing correct username and password combination on the login page and clicking "login", I get the following error message on the target login page: "Sorry, something went wrong. Please try again.". This only occurs when running through browser automation. Just wondering if there's a workaround for this issue. Here is my code thus far:
from selenium import webdriver
from selenium.common.exceptions import NoSuchElementException
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By
import time
PATH="C:\Program Files (x86)\chromedriver.exe"
driver = webdriver.Chrome(PATH)
btn_sign_in_nav = "//span[text()='Sign in']"
btn_sign_in_drop_down = "//div[#id='accountMenu']//div[text()='Sign in']"
input_username_login = "//input[#id='username']"
input_password_login = "//input[#id='password']"
btn_submit_login = "//button[#id='login']"
def xpath_explicit_wait(xpath_val, time_sec):
if type(time_sec) != int or type(xpath_val) != str:
print("NUMERICAL VALUES ONLY!")
driver.quit()
try:
element = WebDriverWait(driver, time_sec).until(
EC.presence_of_element_located((By.XPATH, xpath_val))
)
except NoSuchElementException:
driver.quit()
def login_user(url, username, password):
driver.get(url)
driver.implicitly_wait(3)
driver.find_element_by_xpath(btn_sign_in_nav).click()
xpath_explicit_wait(btn_sign_in_drop_down, 5)
driver.find_element_by_xpath(btn_sign_in_drop_down).click()
driver.implicitly_wait(3)
driver.find_element_by_xpath(input_username_login).send_keys(username)
driver.find_element_by_xpath(input_password_login).send_keys(password)
xpath_explicit_wait(btn_submit_login, 5)
driver.find_element_by_xpath(btn_submit_login).click()
There are detection mechanisms on sites like target that detect when you're using selenium and prevent the site from working.
More details can be found in the answer here: Can a website detect when you are using Selenium with chromedriver?
PhoenixBot implements a mechanism that changes the contents of the driver so that it's undetectable. Use this same mechanism and your problems will vanish, as mine did! :-D
https://github.com/Strip3s/PhoenixBot/blob/554441b3b6888a9be46b8aed6d364dc33da92e87/utils/selenium_utils.py#L150-L173
There is a bot Phoenixbot, I can't speak for the functionality 100% but the auto login portion definitely works and is python. https://github.com/Strip3s/PhoenixBot/blob/master/sites/target.py
I've been attempting to figure out how exactly it's accomplishing that but no success replicating successfully in my own code. Maybe take a look.... If you figure it out I'd love to know.
IF you have the ability to use Safari webdriver, then see the below code.
import time
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as ec
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.common.action_chains import ActionChains
from selenium.webdriver.common.keys import Keys
driver = webdriver.Safari(executable_path='/usr/bin/safaridriver')
driver.get('https://www.target.com/')
action = ActionChains(driver)
driver.find_element(By.XPATH, '//*[#id="account"]').click()
WebDriverWait(driver, 30).until(ec.presence_of_element_located((By.XPATH, '//*[#id="accountNav-signIn"]')))
action.send_keys(Keys.ENTER)
action.perform()
WebDriverWait(driver, 10).until(ec.presence_of_element_located((By.XPATH, '//h2[#class="sc-hMqMXs sc-esjQYD eXTUDl"]')))
driver.find_element(By.ID, 'username').click()
driver.find_element(By.ID, 'username').send_keys('foo')
time.sleep(5)
driver.find_element(By.ID, 'password').click()
driver.find_element(By.ID, 'password').send_keys('bar')
time.sleep(5)
driver.find_element(By.XPATH, "//button[#id=\'login\']").send_keys(Keys.ENTER)
time.sleep(10)
driver.quit()
As #Decian Shanaghy mentioned, Target seems to be bot protected, but Safari webdriver still works.
The time.waits are not needed, you can remove them if you would like.
For anyone still seeking a solution to this, see this answer at Can a website detect when you are using Selenium with chromedriver?. I did a search through the chromedriver binary executable (MacOS in my case) and changed instances of $cdc_ to $abc_.
I originally suspected Target employs a JavaScript solution to hunting selenium users. I confirmed this suspicion by using selenium to open a browser at https://www.target.com without any automation. I attempted to manually login and obtained a 401 response with the well known "Sorry, something went wrong. Please try again." That didn't rule out a UI-based bot hunting solution but it pointed to a JavaScript hunter.
I am using selenium webdriver to open a page in my website using python.
The page link is : "www.example.com/App/Details.aspx/I=5aM%+8KbCv1o=&T=M30Lr7RtcdR=&H=fRFKse5fKA=="
Since I cannot open this page directly, I have to first login on
www.example.com, which I am doing this way:
from selenium.common.exceptions import TimeoutException
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
driver = webdriver.Firefox()
try:
driver.set_page_load_timeout(10)
driver.get('http://www.example.com')
except Exception:
print ('time out')
#driver.find_element_by_id("Default").send_keys(Keys.CONTROL +'Escape')
username = driver.find_element_by_id("usrid")
password = driver.find_element_by_id("pswd")
username.send_keys("Sample_user")
password.send_keys("samplepass")
driver.find_element_by_id("submitbtn").click()
After this I am am able to log in successfully,
but when I redirect to the above link using
driver.get("www.example.com/App/Details.aspx/I=5aM%+8KbCv1o=&T=M30Lr7RtcdR=&H=fRFKse5fKA==")
I get error saying please login first. Please suggest a solution for the same.
You sent the data via
password.send_keys
but after that you were to also send enter command using
password.send_keys((Keys.ENTER)
After this you have to have a
sleep(1)
or
WebDriverWait Until(expect...
before you open the next page
I'm trying to control Spotify's browser player. All of the controls are put inside iframe sections.
Problem: The iframes are EMPTY in the Selenium WebDriver object. Yet, the iframes are filled with the correct content in the ACTUAL browser.
Code sample:
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as ec
import time
username = 'myusername'
base_url = 'https://play.spotify.com/user/spotifydiscover/playlist/76HML2OQXigkyKopqYkeng'
browser = None
def login():
global browser
password = input("Password: ")
browser = webdriver.Firefox()
browser.get(base_url)
browser.find_element_by_id('has-account').click()
browser.find_element_by_id('login-usr').clear()
browser.find_element_by_id('login-usr').send_keys(username)
browser.find_element_by_id('login-pass').clear()
browser.find_element_by_id('login-pass').send_keys(password)
browser.find_element_by_id('login-pass').submit()
def next_track():
global browser
wrapper = browser.find_element_by_id("section-collection")
print(wrapper.get_attribute('innerHTML').encode('utf-8'))
iframe = wrapper.find_element_by_tag_name('iframe')
print(iframe.get_attribute('innerHTML').encode('utf-8'))
sub = browser.switch_to_frame(iframe)
sub.find_element_by_id('next').click()
def test():
login()
time.sleep(14) # Adjusted until page is 100% fully loaded
next_track()
time.sleep(40)
The problem is here:
iframe = wrapper.find_element_by_tag_name('iframe')
There are multiple iframes on the page and you are interested in the one with app-player id:
browser.switch_to_frame("app-player")
# now use browser.find_element_* to locate elements inside iframe
Also note that using time.sleep makes your automation code seriously fragile and usually slower than needed - instead use Explicit Waits to wait for the specific conditions to be met on a page.