I am trying to make a python program using selenium that opens the browser and does some stuff, waits for the user to click on a button, then selenium takes over again. I know that I am supposed to use an explicit wait but I do not know how to make selenium wait for the user to click a button on the browser before continuing with my code.
Here is a summary of my code so far:
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By
from selenium.webdriver.support.select import Select
from selenium.webdriver.support.ui import WebDriverWait
driver_path = my_driver_path
driver = webdriver.Chrome(executable_path=driver_path, chrome_options=options)
driver.get(my url)
... (Some code that does automation stuff until a certain point)
#What do I do here?
wait = WebDriverWait(driver, 10)
...(After the user clicks I want the program to resume)
Presumably, something on the website changes when the user clicks on the button. Define that change as the wait condition.
For example, if you expect an element to pop up:
def is_visible(by, identifier):
def condition(driver):
elems = driver.find_elements(by, identifier)
ele = elems and elems[0]
exists_and_displayed = ele and ele.is_displayed()
return exists_and_displayed
return condition
wait.until(is_visible(By.ID, 'added_or_unhidden_after_click'))
Or if you expect something to disappear:
def is_not(condition):
#ft.wraps(condition)
def wrapper(driver):
return not condition(driver)
return wrapper
wait.until(is_not(is_visible(By.ID, 'removed_or_hidden_after_click')))
(typed from memory, might have a syntax error or so, but you should get the idea)
(The built-in expected_conditions as EC basically do these same things, but I run into small issues with them here and there the way they're written, so I prefer to roll my own.)
Related
Python/coding newb, beware!
Im writing a script to download from youtube from " https://ytmp3.cc/en13/ ". I had written a click script using pyautogui but the problem being that the download button appears anywhere betweeen 1 and 15 seconds of entering the link. So i wanted to re-code it in a Selenium window to dynamically wait until the button is visible and then continue with the click script. I have tried about 15 ways but cant get it to work
library blah :
from selenium import webdriver
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.common.by import By
from selenium.webdriver.support.expected_conditions import presence_of_element_located
from selenium.common.exceptions import NoSuchElementException
from selenium.webdriver.support import expected_conditions as EC
from selenium.common.exceptions import TimeoutException
ways i tried to get it to work:
without waits, results in NosuchElement Exception
def check_exists():
try:
while True:
a=driver.find_element(By.LINK_TEXT, "Download")
a.click()
except NoSuchElementException:
time.sleep(10)
the syntax of this is most probably wrong
i tried a couple different variations of implicit and explicit waits but couldnt get it to work. Is there some javascript on the site linked above thats messing with my code?
in a separate .py, running
#driver.find_element(By.LINK_TEXT, "Download").click()
#either the line above or below works at finding the element, and clicking it
driver.find_element_by_link_text("Download").click()
I just need help getting the line above ^ into an explicit wait, but i dont have the language knowledge of how to do it yet. i would appreciate some help, thanks in advance!
You can use webdriver wait to wait until button is displayed. Tried the below code which works for me
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By
video_path = "your_video_path"
waitTime=10
driver = webdriver.Chrome("./chromedriver.exe")
driver.get("https://ytmp3.cc/")
element = driver.find_element_by_id("input")
element.send_keys(video_path)
driver.find_element_by_id("submit").click()
try:
# wait 10 seconds before looking for element
element = WebDriverWait(driver, waitTime).until(
EC.presence_of_element_located((By.LINK_TEXT,"Download"))
)
driver.find_element_by_link_text("Download").click()
finally:
print(driver.title)
You can update your required wait time in waitTime variable in seconds so if the value is 10 selenium will wait and check for elements upto 10 seconds
Objective:
Run a continuous function to keep clicking a button on target url page with wait between clicks
url = "https://kingoftheclicks.com/?ref=ghost-of-a-chance"
target button = "+ Click button"
Later I will set it to target opponent "clicks - 1,000"
//*[#id="__layout"]/div/main/div[3]/div[3]/div/div[2]/div/div[2]/div[1]/div[3]/text()[2]
Need help getting this basic code to work and click button.
from selenium.webdriver.common.action_chains import ActionChains
elem = driver.find_element_by_xpath('//a#id="__layout"]/div/main/div[3]/div[3]/div/div[2]/div/div[2]/div[2]/div[2]/div[2]')
actions = ActionChains(driver)
actions.click(elem).perform()
You can use a loop to do an action over and over. For example, to print something 10 times:
for i in range(10):
print("foo")
You can also use while loops, whose syntax is something like:
while [some_condition_is_true]:
[do something]
If you need to wait between each click, you can sleep:
import time
time.sleep(0.1) #This will pause the program for 100 milliseconds
You first need a better locator! then you should use WebDriverWait.
As #Kosay suggested to use while here is an implementation:
driver.get("https://kingoftheclicks.com/?ref=ghost-of-a-chance")
WebDriverWait(driver,30).until(EC.element_to_be_clickable((By.CSS_SELECTOR, "button.advance")))
driver.find_element(By.CSS_SELECTOR, "button.advance").click()
WebDriverWait(driver,30).until(EC.presence_of_all_elements_located((By.CSS_SELECTOR, ".fighter--challenger .fighter-btn")))
while driver.find_element(By.CSS_SELECTOR,".fighter--challenger .fighter-btn").is_displayed():
driver.find_element(By.CSS_SELECTOR, ".fighter--challenger .fighter-btn").click()
Note: I added WebDriverWait so you'll need to import it too.
Here are the imports:
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
I am trying to close a pop up window with selenium in python, which is not allowing my code to execute further. But I am unable to do that. There is a a pop up window which asks me if i want to sign up but it keeps popping up at inconsistent times. Is there a method to check wether or not the pop-up window is active?
My code so far:
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
import time
PATH = "C:\Program Files (x86)\chromedriver.exe";
driver = webdriver.Chrome(PATH);
driver.get("https://www.investing.com/news/")
time.sleep(3)
accept_cookies = driver.find_element_by_xpath('//*[#id="onetrust-accept-btn-handler"]');
accept_cookies.click();
So your problem is that you don't want the signup popup to display.
I was just poking the site's script, I found a really nice way for you to work around it: set user agent to gene. The script to display popup will be disabled if user agent matches some mobile browsers.
import time
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
opts = Options()
opts.add_argument("user-agent=gene")
driver = webdriver.Chrome(options=opts)
# Adds the cookie into current browser context
driver.get("https://www.investing.com/news/")
time.sleep(60) # wait for a minute to see if the popup happens
driver.quit()
Run this code, observe the page, it will not display the signup popup.
Alternative work around:
Use a Chrome profile that already turned off the Signup popup, will also not display the popup
from selenium import webdriver
options = webdriver.ChromeOptions()
options.add_argument("user-data-dir=C:\\Path") #Path to your chrome profile
If you really need to close the popup without these methods, define a check function with try/except. Before doing any actions, call this function to check if there's popup, then close the popup, save the state to some variable (so you don't check it anymore). Since the function has try/except, it will not raise Exception and your code will run.
You can do this with 2 quick methods that I can think of immediately.
1:
You will use this often
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
then when you want to get an element that needs time to load and you want to do actions with it, you implement it with WebDriverWait :
wait = WebDriverWait(driver, 10)
try:
accept_cookies = wait.until(EC.presence_of_element_located((By.XPATH, "'//*
[#id=\"onetrust-accept-btn-handler\"]'")))
catch:
# probably you have a bad locator and the element doesn't exist or it needs more than 10 sec to load.
else:
# logic here is processed after successfully obtaining the pop up
accept_cookies.click()
I would recommend using ActionChains
from selenium.webdriver.common.action_chains import ActionChains
then after you obtain the pop up element make the click like this:
actions = ActionChains(driver)
actions.move_to_element(accept_cookies).click().perform()
This is the equivalent of moving the mouse pointer to the middle of the pop up close btn and clicking it
Hello I am new to python and I am trying to create an automation bot (I am very new to python) that logs into instagram and likes a certain number of posts but I am trying to figure out how to add a delay from when it enters the username information and password but I am not sure how to go about that, Also I would appreciate any feedback/recommendations thank you. Here is the code I have so far
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
browser = webdriver.Chrome()
def site_login():
browser.get('https://www.instagram.com/')
browser.find_element_by_name("username").send_keys(‘username’)
browser.find_element_by_name("password").send_keys(“password”)
browser.find_element_by_name("Log In").click() #not sure if this works
The time module should help you
import time
time.sleep(seconds) #Enter the time in seconds here
If you want to wait for a specified period then you can use time.sleep(timeInSeconds) which need import time.
import time
time.sleep(number_of_seconds)
But, however I would like to use the explicit wait. Unlike hard timeout, this will wait until the condition is met and continue the script.
# needed the imports
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.ui import WebDriverWait
# wait for the element and click (using xpath locator)
WebDriverWait(browser, 10).until(EC.presence_of_element_located((By.XPATH, "xpath_goes_here"))).click()
# wait for the element and enter value (using css locator)
WebDriverWait(browser, 10).until(EC.presence_of_element_located((By.CSS_SELECTOR, "css_locator_goes_here")))).send_keys("enter input")
# store the element and then perform action
loginButton = WebDriverWait(browser, 10).until(EC.presence_of_element_located((By.CSS_SELECTOR, "css_locator_goes_here"))))
loginButton.click()
you can use either CSS or xpath location strategy.
You can also use implicit wait at the driver level by adding below line of code.
browser.implicitly_wait(10)
Instead of using time.sleep(seconds) , I would recommend to use Explicit wait as the previous comment. Since due to environment changes time can be vary. So its better to use Explicit wait. Using time.sleep(seconds) will sleeps the current thread. It's a bad practice.
Thanks
I am trying to use Selenium in Python, as as I am a beginner in doing so I cannot get send_key to work, but most probably it is straight forward and I am missting something.
Here is an example of what I have done so far:
from selenium import webdriver
driver = webdriver.Firefox()
driver.get("https://semantria.com/demo")
item = driver.find_element_by_id("analyze_url_form")
item.send_keys("http://finance.yahoo.com/news/skystar-bio-pharmaceutical-company-provides-133000048.html")
go_button = driver.find_element_by_id("analyze_url_button")
go_button.click()
The idea is that in the https://semantria.com/demo website, there is an empty space that one can enter a website link, and then click on the Go button.
However, it looks like my code does not do this.
Am I doing something wrong? Does this website do something that I should be aware of and change my code accordingly?
Any help on this is really appreciated.
The problem is that you are sending keys to the form element, not the input element inside.
Plus, you can just send the URL with a new line at the end which is the same as you've entered the URL and pressed ENTER key which results in the form being submitted. Works for me:
item = driver.find_element_by_css_selector("form#analyze_url_form input[name=link]")
item.send_keys("http://finance.yahoo.com/news/skystar-bio-pharmaceutical-company-provides-133000048.html" + "\n")
As a bonus, here is how you can grab the sentiment value (you have to let selenium know what to wait for via WebDriverWait and Expected Conditions):
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
driver = webdriver.Firefox()
driver.get("https://semantria.com/demo")
item = driver.find_element_by_css_selector("form#analyze_url_form input[name=link]")
item.send_keys("http://finance.yahoo.com/news/skystar-bio-pharmaceutical-company-provides-133000048.html" + "\n")
wait = WebDriverWait(driver, 30)
sentiment_value = wait.until(EC.visibility_of_element_located((By.CSS_SELECTOR, "strong.sentiment_score_value")))
print(sentiment_value.text)
Prints positive (+0.230).