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()
Related
I've seen similar questions to this but no one has given me a clear answer on whether or not it is possible for Selenium to know whether the entire page has loaded or not.
I know about expected_conditions.visibility_of_element_located((By.TAG_NAME, "div")) but I do not want a dynamic element to look for. I also don't want to wait a set number of seconds, I need the program to continue as soon as the entire page is loaded.
Is this possible?
You can use selenium webdriverWait:
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")
element = WebDriverWait(driver, 10).until(
EC.presence_of_element_located((By.ID, "myDynamicElement"))
)
In the code above, Selenium will wait for a maximum of 10 seconds for an element matching the given criteria to be found. If no element is found in that time, a TimeoutException is thrown.
Or you can use the time module:
import time
time.sleep(10)
In the code above the program will wait for 10 seconds before executing the next line.
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 tried this
WebDriverWait(web.driver,1000000000000000000000000000000000000000000000000)
and it did nothing literally nothing.
The web is also changing dynamically new elements are introduced to it and the code doesn't exist in the page_source of the new elements.
please help I have been stuck on this all morning
I'm using geckodriver for firefox
python 3
test code
_browser_profile = webdriver.FirefoxProfile()
_browser_profile.set_preference("dom.webnotifications.enabled", False)
driver=webdriver.Firefox(firefox_profile= _browser_profile)
driver.get("https://www.google.com/")
wait= WebDriverWait(driver,10)
driver.get("https://www.youtube.com")
This is just declaration of explicit wait.
This will do nothing WebDriverWait(web.driver,1000000000000000000000000000000000000000000000000) , if you do not bind it with EC which is expected conditions.
Something like this you have to do :
wait = WebDriverWait(driver, 10)
element = wait.until(EC.element_to_be_clickable((By.ID, 'someid')))
More about Explicit wait can be found at Selenium python wait
UPDATE :
The code you have shared , you are just letting your script know that it has explicit wait.
You are not using explicit wait at all.
driver.get("https://www.google.com/")
search_bar = wait.until(EC.element_to_be_clickable((By.NAME, 'q')))
search_bar.sendkeys("Hi Google")
Note that, you have to import this :
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
I do not know why #Andrei has provided you the worst kind of explicit wait which is nothing but time.sleep(10) which should be avoided as much as possible.
Code at Selenium by python
from selenium import webdriver
from selenium.webdriver.support.select import Select
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
from selenium.webdriver.common.action_chains import ActionChains
driver = webdriver.Chrome()
driver.maximize_window()
driver.get("https://motul.lubricantadvisor.com/Default.aspx?data=1&lang=ENG&lang=eng")
def getallcars():
wait = WebDriverWait(driver, 10)
wait.until(EC.presence_of_element_located((By.ID, "ctl00_ContentPlaceHolder1_rptCategoryBtn_ctl01_btnImage")))
driver.find_element(By.ID, "ctl00_ContentPlaceHolder1_rptCategoryBtn_ctl01_btnImage").click()
wait.until(EC.presence_of_element_located((By.ID, "ctl00_ContentPlaceHolder1_lblSelectedMake")))
driver.find_element(By.ID, 'ctl00_ContentPlaceHolder1_lblSelectedMake').click()
wait.until(EC.presence_of_element_located((By.CSS_SELECTOR, "#ctl00_ContentPlaceHolder1_lstMake")))
el = driver.find_element(By.NAME,"ctl00$ContentPlaceHolder1$lstMake")
car =[]
for option in el.find_elements(By.TAG_NAME,'option'):
car.append((option.text).encode('utf8'))
return car
cars=getallcars()
for value in cars:
drop = driver.find_element(By.CSS_SELECTOR, '#ctl00_ContentPlaceHolder1_lstMake')
sel = Select(drop)
sel.select_by_visible_text(value)
time.sleep(2) #<---- THIS POINT!!
driver.find_element(By.ID,'ctl00_ContentPlaceHolder1_HeaderModel').click()
el2 = driver.find_element(By.NAME, "ctl00$ContentPlaceHolder1$lstModel")
print "The models for %s are:" %value
for option in el2.find_elements(By.TAG_NAME,'option'):
print option.text
action = ActionChains(driver)
action.move_to_element_with_offset(el2, 300, 200)
action.click()
action.perform()
driver.find_element(By.CSS_SELECTOR,'#ctl00_ContentPlaceHolder1_HeaderMake').click()
I have been make the crawler. I don't understand completely yet. so I have a question. maybe It's 34line at code. I was mark about #
it's use be the "time.sleep(2)" method. because It didn't detect the select box when It's change about "sel.select_by_visible_text(value)"
how can I do that? I don't want to use the "time.sleep(2)"method.
already I tried "expected_conditions.presence_of_element_located" It doesn't work. I guess It's problem about dropbox. this size is not basically because It did well when I tried another size tried "expected_conditions.presence_of_element_located"
Explicit wait will not work, because the conditions you can use are "element to be clickable", "element to be visible" and like that.
The element that you using for explicit wait is available and clickable also, but its failing because other element is overlapping it.
Since the other element's overlap takes time to disappear, we have to wait for the overlap to disappear before we can click on the element.
Explicit wait can wait for element to appear and clickable, which it is already is but it is being hidden by other element.
In this scenario, we have to use time.sleep() to put a hard wait
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.