How can I refresh the Python Selenium until I can click xpath?
xpath_click = '//*[#id="wrapcalendar"]/div[2]/div/div[1]/table/tbody/tr[5]/td[5]'
while True:
element = driver.find_element_by_xpath(xpath_click)
if element.text == 'xpath_click':
element.click()
break
else :
driver.refresh()
driver.implicitly_wait(1)
You were fairly close, few things:
You should know the expected string in advance, based on that we will have an if condition, see below.
wrap the risky code inside try and except block.
You should wait (hardcoded) for at least 2 seconds so that page refresh is done successfully.
Code:
while True:
try:
element = driver.find_element(By.XPATH, xpath_click).text
if element == "your expected string here":
element.click()
print("Clicked on the element so break from infinite loop.")
break
else:
driver.refresh()
time.sleep(2)
except:
print("Something went wrong")
break
pass
I am not sure why are you putting this inside an if loop, have you tried waiting for an element? Example suited for your scenario:
from selenium.webdriver.support import expected_conditions as EC
wait = WebDriverWait(driver, 10)
element = wait.until(EC.element_to_be_clickable((By.xpath, '//*[#id="wrapcalendar"]/div[2]/div/div[1]/table/tbody/tr[5]/td[5]')))
element.click()
Related
I'm trying to do the test to learn Allure, and to assure that the test is passed, the button has to be INVISIBLE. It first clicks 1st button to make 2nd button appear. Then click 2nd button - so same (2nd button disappears). Here it is: http://the-internet.herokuapp.com/add_remove_elements/
My code would look like this (below), it clicks the 1st button, 2nd button - and after it should check that button DELETE is not visible anymore. Instead it interrupts whole code and throws error that element was not found/located.
How do you make it so it will not interrput/cancel whole codeblock when it doesn't find this button?
class TestPage:
def test_button(self):
s=Service('C:\Program Files\chromedriver.exe')
browser = webdriver.Chrome(service=s)
browser.get("http://the-internet.herokuapp.com/")
browser.maximize_window()
time.sleep(1)
add = browser.find_element(By.XPATH, "/html/body/div[2]/div/ul/li[2]/a")
add.click()
time.sleep(1)
button = browser.find_element(By.XPATH, "/html/body/div[2]/div/div/button")
button.click()
time.sleep(1)
deleteButton = browser.find_element(By.XPATH, "/html/body/div[2]/div/div/div/button")
deleteButton.click()
deleteCheck = browser.find_element(By.XPATH, "/html/body/div[2]/div/div/div/button").is_displayed()
if deleteCheck == False:
assert True
else:
assert False
time.sleep(1)
browser.close()
Here's edited code (with last step trying to go to main page):
def test_button(self):
s=Service('C:\Program Files\chromedriver.exe')
browser = webdriver.Chrome(service=s)
browser.get("http://the-internet.herokuapp.com/")
browser.maximize_window()
wait = WebDriverWait(browser, 3)
time.sleep(1)
add = browser.find_element(By.XPATH, "/html/body/div[2]/div/ul/li[2]/a")
add.click()
time.sleep(1)
button = browser.find_element(By.XPATH, "/html/body/div[2]/div/div/button")
button.click()
time.sleep(1)
browser.save_screenshot('buttons.png')
time.sleep(1)
delete = browser.find_element(By.XPATH, "/html/body/div[2]/div/div/div/button")
delete.click()
time.sleep(1)
wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR, "button[onclick*='delete']"))).click()
time.sleep(0.5)
if not browser.find_elements(By.CSS_SELECTOR, "button[onclick*='delete']"):
assert True
else:
assert False
time.sleep(0.5)
browser.get("http://the-internet.herokuapp.com/")
After clicking the delete button it disappears. Not only becomes invisible but no more present on the page.
The clearest way to validate web element is not presented is to use find_elements method. This method return a list of elements found matching the passed locator. So, in case of match the list will be non-empty and in case of no match the list will be empty. Non-empty list is indicated by Python as Boolean True, while empty list is indicated as Boolean False. No exception will be thrown in any case.
Additionally, you need to improve your locators and use WebDriverWait expected_conditions explicit waits, not hardcoded sleeps.
The following code worked for me:
import time
from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
options = Options()
options.add_argument("start-maximized")
options.add_argument('--disable-notifications')
webdriver_service = Service('C:\webdrivers\chromedriver.exe')
driver = webdriver.Chrome(options=options, service=webdriver_service)
wait = WebDriverWait(driver, 10)
url = "http://the-internet.herokuapp.com/add_remove_elements/"
driver.get(url)
wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR, "button[onclick*='add']"))).click()
wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR, "button[onclick*='delete']"))).click()
time.sleep(0.5)
if not driver.find_elements(By.CSS_SELECTOR, "button[onclick*='delete']"):
print("Delete button not presented")
you can try this code to wait for that element in 15 second
and if it does not appear then continue code
try:
WebDriverWait(self.browser, 15).until(EC.visibility_of_all_elements_located((By.XPATH, "/html/body/div[2]/div/div/div/button")))
...
except:
continue
You can wrap the deleteCheck in a try block:
try:
deleteCheck = browser.find_element(By.XPATH, "/html/body/div[2]/div/div/div/button")
assert False
except NoSuchElementException:
assert True
The purpose is I want to check the button is exist on web page and then click it, if not exist, just skip.
But, it's not works if not 'is_displayed()', please suggest me how can I modify the code, thanks!
Here is the code:
button = wait.until(EC.element_to_be_clickable((By.XPATH, '//*[#id="ra_on"]')))
if button.is_displayed() == True:
button.click() #means turn to ON. It's works.
else:
print('It's ON ready.') #means turn ON ready. It's not works.
Use find_elements that will return a list of Web element, if found at least one Web element, if it does not find anything the list will be empty.
Code:
try:
if len(driver.find_elements(By.XPATH, "//*[#id='ra_on']")) > 0:
print("element must be displayed, do whatever you wanna do here")
button = wait.until(EC.element_to_be_clickable((By.XPATH, "//*[#id='ra_on']")))
button.click()
else:
print("Element with xpath //*[#id='ra_on'] not found.")
except:
print("Just skip it")
pass
To click on the button if it is clickable or else just to skip you can wrap up the line within a try-except{} block and you can use the following solution:
try:
WebDriverWait(driver, 10).until(EC.element_to_be_clickable((By.XPATH, '//*[#id="ra_on"]'))).click()
except TimeoutException:
pass
Note: You have to add the following imports :
from selenium.common.exceptions import TimeoutException
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
My selenium webdriver been constantly crashing due to
TimeoutException: Message: timeout: Timed out receiving message from
renderer: 298.972
The cookies pop up opens up but the script doesn't click on it,
in like 20 driver.get(url), 19 times it will accept cookies but the 20th will fail to accept cookies, although the window has opened up, I tried to use the code below but still fails.
retries = 1
while retries <= 5:
try:
element = WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.XPATH, '//*[#class="coi-banner__accept"]'))) #wait until cookies clickable
element.click()
break
except TimeoutException:
driver.refresh()
element = WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.XPATH, '//*[#class="coi-banner__accept"]'))) #wait until cookies clickable
element.click()
retries += 1
I ran the below script more than 20 times and still it was able to click on the desired button every single time.
All I had to do was basically to change the locator to CSS from XPath:
driver = webdriver.Chrome(driver_path)
driver.maximize_window()
wait = WebDriverWait(driver, 30)
driver.get("https://www.novasol.com/")
try:
wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR, "button[onclick='CookieInformation.submitAllCategories();']"))).click()
print('Clicked it')
except:
print('Either element was not found, or Bot could not click on it.')
pass
Imports:
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
Updated:
driver.get("https://www.novasol.com/")
def retry_click(number_of_retries, wait_before_performing_click):
while number_of_retries > 0:
time.sleep(wait_before_performing_click)
try:
wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR, "button[onclick='CookieInformation.submitAllCategories();']"))).click()
break
except:
pass
number_of_retries = number_of_retries - 1
try:
wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR, "button[onclick='CookieInformation.submitAllCategories();']"))).click()
print('Clicked it')
except:
print('Either element was not found, or Bot could not click on it.')
driver.refresh()
retry_click(20, 10)
pass
Try to use driver.execute_script() instead of element.click()
htmlElement = driver.find_element_by_xpath('//*[#class="coi-banner__accept"]')
driver.execute_script("arguments[0].click();", htmlElement)
Generally,
element = WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.XPATH, '//*[#class="coi-banner__accept"]'))) #wait until cookies clickable
element.click()
should work. From the code you shared I can't see why it works in 95% cases but fails in 5% case.
What I do see:
You are trying to find exactly the same condition in except block that caused the TimeoutException.
So, if somehow Selenium could not find element matching this locator //*[#class="coi-banner__accept"] to be clickable and thrown an TimeoutException waiting for the same condition in except will give you the same result....
Also, I see no sense to put this in a loop of 5 attempts.
In case element was found, clicked and closed - no sense to try again.
And in case you could not do that in the first attempt - this will throw you TimeoutException exception on the first attempt, you will never continue to the second attempt here...
So i am trying to pre-order the latest PS5 (during the sale )for which i thought to write a python script bot(Newbie to python) .I managed to write the below for another product .However the total time taken till i reach the final transaction page is just over 1 min ,and that too when the server is not loaded .
Is there anything i can do make the transaction run faster till the last page under 30 secs if possible ?
And since i am a newbie trying to learn from automate the boring stuff from python ,Plese suggest some what improvements can i make on my code ?
Also is there a possible way to run this headless till i enter my otp to confirm the transaction its basically the last page for which i am not using headless mode?
...
from selenium import webdriver
import time
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.desired_capabilities import DesiredCapabilities
op = webdriver.ChromeOptions()
#op.add_argument('headless')
op.add_argument('disable-infobars')
op.add_argument('disable-extensions')
caps = DesiredCapabilities().CHROME
caps["pageLoadStrategy"] = "none"
url ='https://www.flipkart.com/latibule-scratch-remover-wax/p/itm251fceb778c9f?pid=SCAG2W9BU2GEJFUW&lid=LSTSCAG2W9BU2GEJFUWHKPRKY&marketplace=FLIPKART&q=car+scratch+remover&store=1mt%2Fuhg%2Fzfb%2F2wf&srno=s_1_2&otracker=AS_QueryStore_OrganicAutoSuggest_1_8_na_na_na&otracker1=AS_QueryStore_OrganicAutoSuggest_1_8_na_na_na&fm=SEARCH&iid=3cbc56ce-4032-4ad3-9f8c-f58e3572b637.SCAG2W9BU2GEJFUW.SEARCH&ppt=sp&ppn=sp&ssid=duj7dx9q340000001622962739970&qH=7307be34aace13e8'
browser=webdriver.Chrome(desired_capabilities=caps, executable_path=r'C:\FAST\Python\3.7.0\chromedriver.exe',options=op)
browser.get(url)
i=0
while True:
try:
element = WebDriverWait(browser, 1).until(
#EC.presence_of_element_located((By.ID, "myDynamicElement"))
EC.element_to_be_clickable((By.CSS_SELECTOR, "._2KpZ6l._2U9uOA.ihZ75k._3AWRsL"))
)
break
except:
# print('element not found/not clickable')
continue
print('element found')
try:
while (element.is_enabled()):
element.click()
except:
print(url)
flag=1
while(browser.current_url):
try:
if (flag ==1):
elem =browser.find_element_by_css_selector('input._17N0em')
while(not elem.get_attribute('value')):
elem.send_keys('8xxxxxxxxx')
elem.send_keys(Keys.ENTER)
flag=2
elif (flag==2):
elem =browser.find_element_by_css_selector('input[type=password]')
while(not elem.get_attribute('value')):
elem.send_keys('111#1234')
time.sleep(2)
elem.send_keys(Keys.ENTER)
flag=3
elif(flag==3):
elem =browser.find_element_by_id('to-payment')
while( elem is None):
continue
elem.click()
flag=4
elif(flag==4):
elem =browser.find_element_by_css_selector('input._1w3ZZo._2mFmU7')
while( elem is None):
continue
elem.send_keys('xxx')
elem.send_keys(Keys.ENTER)
flag= 5
elif (flag==5):
break
except:
continue
print('end')
print(url)
print(browser.current_url)
...
I see 2 things I would make it other.
1)
element = WebDriverWait(browser, 1).until(EC.element_to_be_clickable((By.CSS_SELECTOR, "._2KpZ6l._2U9uOA.ihZ75k._3AWRsL"))
If that element is normally expected to appear there you should use much longer timeout. Since this is not a kind of sleep, Selenium will continue exactly on the moment it detects that element clickable. On the other hand too short timeouts will cause timeout exceptions in many cases if the web page had not complete loading in that limited time period
2)
try:
while (element.is_enabled()):
element.click()
I'm not sure it's a good practice to click on the same element with infinite loop while clicks are performed with a very short delays, actually kind of bombing that element maybe thousands times in a second...
I am currently attempting to get my code to keep refreshing the page until a specific element on the website becomes clickable. Sample code is provided below:
lolSize = False
while not lolSize:
try:
if size.is_enabled():
driver.execute_script("arguments[0].click();", size)
lolSize = True
except:
time.sleep(1)
driver.refresh()
Now if I put a value that is clickable at the exact moment of running the code, it works just fine. However, if a value that isn't clickable at the moment is used, the page does not refresh at all. Apologies if something rudimentary is incorrect with my code, I'm very much a novice in Python. Any help is appreciated, and if you need clarification regarding my issue, don't hesitate to ask! Thank you! :)
You must handle the else condition of your if statement
while not lolSize:
try:
assert size.is_enabled()
driver.execute_script("arguments[0].click();", size)
lolSize = True
except:
time.sleep(1)
driver.refresh()
The assert will raise an exception if it is not true and refresh will occur in the exception handler code.
Also, I believe with the code provided, upon refresh the is_enabled() code will always raise an exception. You need to retrieve the size element each refresh to not have a staleElementException. Such exception will loop your code with driver.refresh() each time.
UPDATE
To ensure there is no element clickable, use the WebDriverWait to get time to find the element
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.common.by import By
timeout_in_sec = 5. # how much time to check for a clickable element
wait = WebDriverWait(driver, timeout_in_sec)
wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR, 'yourCssPath')))
With code updated that gives:
wait = WebDriverWait(driver, timeout_in_sec)
while not lolSize:
try:
size = wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR, 'yourCssPath')))
driver.execute_script("arguments[0].click();", size)
lolSize = True
except:
time.sleep(1)
driver.refresh()
Note that (By.CSS_SELECTOR, 'yourCssPath') needs to match the way you previously found size
My idea for this problem would be like that :
while True:
try:
driver.execute_script("arguments[0].click();")
break
except:
time.sleep(1)
driver.refresh()