Wait time between each action - python

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

Related

How to close browser(ChromeDriver) on time using Python

I made a Python program that opens my Youtube playlist using Selenium and I want to close that browser when all video is watched.
(I tried using time.sleep() but the problem is Youtube ads).
So, is there any way I can close my browser automatically when all video is watched?
When the video is finished //div[#class='ytp-autonav-endscreen-button-container'] element appears so you can wait until this element appearing and then close the driver.
You can also simply locate it by the class name 'ytp-autonav-endscreen-button-container' or other buttons / elements inside it.
So after staring the video use
WebDriverWait(driver, delay).until(EC.visibility_of_element_located((By.ID, 'ytp-autonav-endscreen-button-container')))
where delay is time that will be enough to the video to finish.
Lear more about webdriver explicit wait conditions here
Don't forget to add the essential imports
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By
I suggest to make in in steps.
First step:
Wait for the last video in playlist:
By text:
last_video = driver.find_element_by_css_selector("#secondary .index-message.style-scope.ytd-playlist-panel-renderer:nth-child(1)").text == "10 /10"
Or by waiting for the last element in the playlist directly:
last_video = driver.find_element_by_css_selector("#secondary #items>.style-scope.ytd-playlist-panel-renderer:last-of-type").get_attribute("selected")
Second step:
After the first condition is true, wait for this video to finish, with this locator (Replay button)
video_ends = driver.find_element_by_css_selector(".ytp-chrome-controls button[title=Replay]")
For this you'll need to import:
from selenium.webdriver.common.by import By
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
And use it like this:
wait = WebDriverWait(driver, timeout_in_seconds)
wait.until(EC.visibility_of_element_located((By.CSS_SELECTOR, "#secondary .index-message.style-scope.ytd-playlist-panel-renderer:nth-child(1)").text == "10 /10")))
Timeout will depend of the length of playlist.
It is not a quick task, nobody will agree to finish it for you here.

Selenium script to detect presence of button and to click on it when it appears not working

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

Python Selenium - send_keys not sending any information to element

I am trying out Selenium for the first time so I apologize if there is an obvious mistake or problem with my code.
from selenium import webdriver
driver = webdriver.Chrome()
driver.get('https://youtube.com')
searchBox = driver.find_element_by_id('search')
searchBox.send_keys('Programming')
searchButton = driver.find_element_by_id('search-icon-legacy')
searchButton.click()
So I tried this and it loads the page fine but, it does not input any characters into the searchBox (I quadruple checked that the id was correct - copied it directly from the inspector).
NOTE:
My internet is really REALLY slow and it takes YouTube approx. 20 seconds to fully load, so I thought that was an issue so I tried;
...
driver.get('https://youtube.com')
driver.implicitly_wait(30)
searchBox = driver.find_element_by_id('search')
...
But this did not work either.
I did use XPATH instead of finding it by element ID at the start and that did not work.
I checked and copied the XPATHs and IDs directly from the inspector and nothing so far has inputted anything into the textbox.
What could be the problem? (1)
and does the webdriver wait for the page to load/find the element before doing anything after it being initialized with the driver.get('websiteAddress')? (2)
NOTE: I double checked that I was selecting the right element as well.
To send keys to the input tag with id = search. We use webdriver waits to allow the element to be usable after driver.get so the page loads correctly.
driver.get('https://youtube.com')
WebDriverWait(driver, 30).until(EC.element_to_be_clickable((By.XPATH, "//input[#id='search']"))).send_keys("Programming")
Import
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
If you don't know the waiting time:
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By
delay = 40
WebDriverWait(driver, delay).until(EC.presence_of_element_located((By.XPATH, "//form[#role='form']//input[#id='username']")))
Then it just waits on the element, for as log as delay is, but will continue as soon as the element is found, that the best way to wait on slow connections.
To relate elements more easily you can use ChroPath, it is an extension for google chrome / edge that allows you to see the path of an element, through cssSelector, Abs XPath, Rel XPath and the tag name, so when your code is not working you can try these other ways. Particularly this extension helps me a lot.

Python Selenium: waiting isn't waiting

I'm designing a web scraper. At a few points I need it to wait for around 10 seconds before jumping to the next action to account for internet connection problems. I want to have a simple implicit wait.
driver.get('MY WEBSITE')
driver.implicitly_wait(10)
menu = driver.find_element_by_link_text("Export")
menu2 = driver.find_element_by_xpath('//td[text()="Data"]')
actions = ActionChains(driver)
actions.move_to_element(menu)
actions.click(menu)
actions.move_to_element(menu2)
actions.click(menu2)
actions.perform()
The only problem is: it's not waiting. I've even tried putting 20 and more secs as the implicitly_wait parameter in order to be completely sure and there was no change. It's opening the website and going directly to search for the two elements. Can anyone explain that please?
From the docs:
An implicit wait tells WebDriver to poll the DOM for a certain amount of time when trying to find any element (or elements) not immediately available. The default setting is 0. Once set, the implicit wait is set for the life of the WebDriver object.
So if the element is immediately available, it won't wait.
Try to use WebDriverWait :
E.g
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
driver = webdriver.Firefox()
driver.get("http://somedomain/url_that_delays_loading")
try:
element = WebDriverWait(driver, 10).until(
EC.presence_of_element_located((By.ID, "myDynamicElement"))
)
finally:
driver.quit()

Selenium webdriver python find element by xpath - Could not find element

I m trying to write a script with selenium webdriver python.
When I try to do a
find_element_by_xpath("//*[#id='posted_1']/div[3]")
it says
NoElementFoundException.
Can someone please help me here?
Regards
Bala
If you are getting NoSuchElementException as your provided exception, There may be following reasons :-
May be you are locating with incorrect locator, So you need to share HTML for better locator solution.
May be when you are going to find element, it would not be present on the DOM, So you should implement WebDriverWait to wait until element visible as below :-
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
wait = WebDriverWait(driver, 10)
element = wait.until(EC.visibility_of_element_located((By.XPATH, "//*[#id='posted_1']/div[3]")))
May be this element is inside any frame or iframe. If it is, you need to switch that frame or iframe before finding the element as below :-
driver.switch_to_frame("frame/iframe I'd or name")
wait = WebDriverWait(driver, 10)
element = wait.until(EC.visibility_of_element_located((By.XPATH, "//*[#id='posted_1']/div[3]")))
#Once all your stuff done with this frame need to switch back to default
driver.switch_to_default_content();
that exception, unsurprisingly, means that that element wasn't available on the DOM. There are a couple of options here:
driver.implicitly_wait(10)
will tell the driver to wait 10 seconds (or any amount of time) after an element is not found/not clickable etc., and tries again after. Sometimes elements don't load right away, so an implicit wait fixes those types of problems.
The other option here is to do an explicit wait. This will wait until the element appears, and until the existence of that element is confirmed, the script will not move on to the next line:
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
element = WebDriverWait(ff, 10).until(EC.presence_of_element_located((By.XPATH, "//*[#id='posted_1']/div[3]")))
In my experience, an implicit wait is usually fine, but imprecise.

Categories