How to get rid of the hardcoded sleep()? - python-3.x

def textfield(boxid,textadded):
project = driver.find_element_by_id(boxid)
project.send_keys(textadded)
sleep(3)
def dropdown(dropdownid, dropdownvalue):
select = Select(driver.find_element_by_id(dropdownid))
select.select_by_visible_text(dropdownvalue)
sleep(5)
These 2 functions are functional however i'm using sleep() which is a bad practice since some my drop-downs and text fields will take longer than others to fill so i have to put the longest sleep value not to get errors, how can i fix these 2 functions using wait.

You can explicitly wait for the element. Read more about waits here. Please note that this is not the official documentation.
#.....
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
#......
select=WebDriverWait(driver, 10).until(EC.presence_of_element_located((By.ID ,dropdownid)))
#....

As you are invoking send_keys() on the WebElement project, ideally you should invoke WebDriverWait with EC as element_to_be_clickable, so you have to:
Replace:
def textfield(boxid,textadded):
project = driver.find_element_by_id(boxid)
project.send_keys(textadded)
sleep(3)
with:
def textfield(boxid,textadded):
WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.ID, "boxid"))).send_keys(textadded)
As the drop-down take longer to fill so you should invoke WebDriverWait with EC as visibility_of_element_located, so you have to:
Replace:
def dropdown(dropdownid, dropdownvalue):
select = Select(driver.find_element_by_id(dropdownid))
select.select_by_visible_text(dropdownvalue)
sleep(5)
with:
def dropdown(dropdownid, dropdownvalue):
select = Select(WebDriverWait(driver, 20).until(EC.visibility_of_element_located((By.ID, "dropdownid"))))
select.select_by_visible_text(dropdownvalue)
Note : You have to add the following imports :
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC

You should use WebDriverWait!
You can use presence_of_all_elements_located on the list of select items...
An example:
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
WebDriverWait(driver, 10).wait.until(EC.presence_of_all_elements_located((By.ID, dropdownid)))
Hope this helps!

Related

Webdriver Selenium click a <li> element inside an Iframe

[![enter image description here][1]][1]trying to click and select the marked
element.
https://i.stack.imgur.com/cIRn8.png
#The options - https://i.stack.imgur.com/e66m1.png
using
from selenium import webdriver
from time import sleep
from selenium.webdriver.support.ui import Select
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
Current attempt:
driver.switch_to.frame(driver.find_element_by_id("moduleManagement")) driver.find_element_by_class_name("ranges").find_element_by_tag_name("ul").find_element_by_tag_name("li").click()
I need help with how to select a
element . where i worng
I would advise you to use explicit wait to switch to frame and interact with them :
to click on second li tag, below code should work for you.
wait = WebDriverWait(driver, 10)
wait.until(EC.frame_to_be_available_and_switch_to_it((By.ID, "moduleManagement")))
wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR, "div#colorbox+div[class^='daterangepicker']"))).click()
second_li_element = wait.until(EC.visibility_of_element_located((By.XPATH, "(//li[#data-range-key])[2]")))
second_li_element.click()
Imports :
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC

In python is possible to create an infinite loop for searching an element in a page?

I'm trying to create an loop for searching a xpath in a page until is available.
I'm trying with this:
cart = driver.find_element_by_xpath('//*[#id="add-to-cart-button"]')
if not cart:
webdriver.ActionChains(driver).send_keys(Keys.F5).perform()
else:
driver.find_element_by_xpath('//*[#id="add-to-cart-button"]').click()
But is impossible to define cart because the xpath is not yet available.
How you do it?
Wrap the click() within a try/catch{} block as follows:
while True:
try:
WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.XPATH, "//*[#id='add-to-cart-button']"))).click()
break
except TimeoutException:
driver.ActionChains(driver).send_keys(Keys.F5).perform()
Note: You have to add the following imports :
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
from selenium.webdriver.common.action_chains import ActionChains

Can't get this selenium web driver to wait. but I can get it to sleep why?

Been struggling on this for a little while now and I'm pulling my hairout. Why does the 1st code not work? But second one does?
'''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
driver = webdriver.Chrome(executable_path='/Users/jackrossanderson/Desktop/chromedriver')
driver.get('https://www.url.Iwanttoscrape.com')
search = driver.find_element_by_name('searchbar')
search.send_keys("hometown")
search.send_keys(Keys.RETURN)
try:
element = WebDriverWait(driver, 10).until(
EC.presence_of_element_located((By.Class_Name, 'button i want to click'))
)
element.click()
driver.back()
except:
print(error)'''
'''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.webdriver.common.by import By
import time
driver = webdriver.Chrome(executable_path='/Users/jackrossanderson/Desktop/chromedriver')
driver.get('https://www.urlIwanttoscrape')
search = driver.find_element_by_name('searchbar')
search.send_keys("home town")
search.send_keys(Keys.RETURN)
time.sleep(12)
element = driver.find_element_by_class_name('button I want to press')
element.click()
driver.back()'''
I know the second way is frowned upon but I cant see why the top one doesnt work?
You can try using
element = WebDriverWait(driver,10).until(EC.element_to_be_clickable((By.CLASS_NAME, "button i want to click"))) to make the driver wait and click based on the class name
Use, element_to_be_clickable is recommended as mentioned here because, presence_of_element_located description defines that it does not necessarily mean the element is visible or clickable.
Also, check the casing for By.CLASS_NAME used.

How to wait until the src attribute is defined using Selenium and Python

I write a program with selenium in python.
My goal is to find the src of the video in the page.
This is my code
video_element = chrome_driver.find_element_by_tag_name("video")
video_src = video_element.get_attribute("src")
When I try to check video_src I get an empty string, however if I put time.sleep(1) before I try to acquire the src I get the real link to the video.
I have tried to use WebDriverWait instead of time.wait like so
video_element = WebDriverWait(chrome_driver, 3).until(
expected_conditions.element_to_be_clickable((By.TAG_NAME, "video"))
)
But I couldn't find any condition that waits until the src tag is filled with the real link.
Is there a way to wait with selenium instead of time? (with time it is not guarantee that the src will be filled)
Please try below solution before that you have to switch to iframe
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait as Wait
from selenium.webdriver.support.ui import WebDriverWait
from selenium import webdriver
driver = webdriver.Chrome(executable_path=r"C:\New folder\chromedriver.exe")
driver.get('https://www.thewatchcartoononline.tv/www-working-episode-1-english-subbed')
driver.switch_to.frame("anime-js-0")
video_element = WebDriverWait(driver, 3).until(EC.visibility_of_element_located((By.ID, "video-js_html5_api")))
val = video_element.get_attribute("src")
print val
Output:
You can try with the below.
video_element = WebDriverWait(chrome_driver, 3).until(
expected_conditions.presence_of_element_located((By.XPATH, "//video[not(#src='')]"))
)
To extract the value of the src attribute you have to induce WebDriverWait for the desired visibility_of_element_located() and you can use either of the following Locator Strategies:
Using CSS_SELECTOR:
print(WebDriverWait(driver, 20).until(EC.visibility_of_element_located((By.TAG_NAME, "video"))).get_attribute("innerHTML"))
Using XPATH:
print(WebDriverWait(driver, 20).until(EC.visibility_of_element_located((By.XPATH, "//video"))).get_attribute("src"))
Note : You have to add the following imports :
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC

Issue with login using selenium and python

I am getting following error
no such element: Unable to locate element: {"method":"xpath","selector":"//input[#placeholder='User ID']"}
(Session info: chrome=78.0.3904.70). Let me know how can i pass user id here
Without additional context, I can only recommend that you wait on the element before sending keys to it:
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
input = WebDriverWait(driver, 30).until(
EC.visibility_of_element_located((By.XPATH, "//input[#placeholder='User ID']")))
input.send_keys("userId")
Full working sample as requested by asker:
from selenium import webdriver
from time import sleep
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
driver = webdriver.Chrome()
driver.get("https://kite.zerodha.com/connect/login?api_key=b8w63qg9m4c3zubd&sess_id=bW3U1OwidO97o11scfeTbyfX4j5tViNp")
input = WebDriverWait(driver, 30).until(
EC.visibility_of_element_located((By.XPATH, "//input[#placeholder='User ID']")))
input.send_keys("userId")
sleep(10) # this sleep is here so you can visually verify the text was sent.
driver.close()
driver.quit()
The above code has succeeded every time I have run it.

Resources