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
Related
I'm trying to simulate clikcin on the "Load more listings" button on the "https://empireflippers.com/marketplace/" webpage untill the button no longer is. I tried the following code but it results in "Move target out bounds" error.
from selenium import webdriver
from selenium.common.exceptions import NoSuchElementException
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
from selenium.webdriver.common.action_chains import ActionChains
HOME_PAGE_URL = "https://empireflippers.com/marketplace/"
driver = webdriver.Chrome('./chromedriver.exe')
driver.get(HOME_PAGE_URL)
while True:
try:
element = WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.XPATH,"//button[contains(text(),'Load More Listings')]")))
ActionChains(driver).move_to_element(element).click().perform()
except Exception as e:
print (e)
break
print("Complete")
time.sleep(10)
page_source = driver.page_source
driver.quit()
I'm expecting to retrieve the html code of the full web page without load more listings button.
So it seems that the button that you are trying to click is not visible on the screen. You could try this:
driver.execute_script("arguments[0].click();", driver.find_element(By.XPATH, "//button[contains(text(),'Load More Listings')]"))
To click the button.
I have no idea why, but trying to click twice works for me. [I still get the same error if I try to click twice with ActionChains, and I'm not familiar enough with ActionChains to try to fix that; my usual approach is to use .execute_script to scroll to the element with JavaScript and then just apply .click() to the element, so that's what I've done below.]
while True:
try:
element = WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.XPATH,"//button[contains(text(),'Load More Listings')]")))
# ActionChains(driver).move_to_element(element).click().perform()
driver.execute_script('arguments[0].scrollIntoView(false);', element)
try: element.click() # for some reason, the 1st click always fails
except: element.click() # but after the 1st attempt, the 2nd click works...
except Exception as e:
print (e)
break
I would like to switch up to two toggles on a website that expand or hide parts of a CMS tree (expanded picture for context) that does not have an API. They are on the same hierarchy level of the tree. The toggles are randomly set on the "hidden" or "expanded" view and I need the first one to be set to hidden and the second to be expanded.
Generally, my code works:
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
from selenium.common.exceptions import TimeoutException
try:
iframe_cms_subpages = WebDriverWait(driver, delay).until(EC.presence_of_element_located((By.XPATH, '/html/body/table/tbody/tr[2]/td[1]/iframe'))) # (unfortunately, I have to go with an abs xpath here)
print("iframe found!")
except TimeoutException:
print("Loading iframe took too long")
driver.switch_to.frame(iframe_cms_subpages)
try:
main_menu1 = WebDriverWait(driver, delay).until(EC.presence_of_element_located((By.XPATH, "//a[#class='npsLogic_nodeViewEntry_c_/main_menu1_npsLogic']/img[#alt='-']")))
print("main_menu1 open! Close it first")
main_menu1.click()
print("closed!")
except TimeoutException:
print("main_menu1 was either already closed or something went wrong.")
try:
main_menu2 = WebDriverWait(driver, delay).until(EC.presence_of_element_located((By.XPATH, "//a[#class='npsLogic_nodeViewEntry_e_/main_menu2_npsLogic']/img[#alt='+']")))
print("main_menu2 closed! Needs to be opened first")
main_menu2.click()
print("main_menu2 opened!")
except TimeoutException:
print("main_menu2 was either already open or something went wrong."
The "+" in the xpath is present if it is closed (hidden), for the "-" it is vice versa (expanded).
My issue: I have tested this in all four scenarios and the code only works if up to one of the two toggles has to be switched to have both be set correctly, i.e. if either both of them are open, both of them are closed or the first one is closed and second one open (correct settings right away). If both of them need to be switched, i.e. if the first one is open and the second one is closed, the second try statement throws a TimeOutException. Why does the second explicit wait not work if an action was performed based on the previous one?
Notes: I included the iframe because I thought it might be relevant; that explicit wait works. I noticed that there is a "c" in the first xpath and an "e" in the second, but that is part of the path for some reason, not a typo.
Do I perhaps have an incorrect understanding of how explicit waits work?
Every time one of the elements is clicked, the elements were not recognized by the webdriver anymore. This can be fixed by just switching back to parent frame and then back into the iframe again! I have also changed the explicit wait type to element_to_be_clickable in line with the recommendation of Greg:
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
from selenium.common.exceptions import TimeoutException
try:
iframe_cms_subpages = WebDriverWait(driver, delay).until(EC.element_to_be_clickable((By.XPATH, '/html/body/table/tbody/tr[2]/td[1]/iframe'))) # (unfortunately, I have to go with an abs xpath here)
print("iframe found!")
except TimeoutException:
print("Loading iframe took too long")
driver.switch_to.frame(iframe_cms_subpages)
try:
main_menu1 = WebDriverWait(driver, delay).until(EC.element_to_be_clickable((By.XPATH, "//a[#class='npsLogic_nodeViewEntry_c_/main_menu1_npsLogic']/img[#alt='-']")))
print("main_menu1 open! Close it first")
main_menu1.click()
print("closed!")
except TimeoutException:
print("main_menu1 was either already closed or something went wrong.")
driver.switch_to.parent_frame()
try:
iframe_cms_subpages = WebDriverWait(driver, delay).until(EC.element_to_be_clickable((By.XPATH, '/html/body/table/tbody/tr[2]/td[1]/iframe')))
print("iframe found!")
except TimeoutException:
print("Loading took too much time or the window was open.")
driver.switch_to.frame(iframe_cms_subpages)
try:
main_menu2 = WebDriverWait(driver, delay).until(EC.element_to_be_clickable((By.XPATH, "//a[#class='npsLogic_nodeViewEntry_e_/main_menu2_npsLogic']/img[#alt='+']")))
print("main_menu2 closed! Needs to be opened first")
main_menu2.click()
print("main_menu2 opened!")
except TimeoutException:
print("main_menu2 was either already open or something went wrong."
i am using python selenium chrome driver and i am stuck at this.
How can i loop this code until one of the elements is clickable?
Like if its finally clickable it should get clicked and print ("clickable") and if its still not clickable it should print ("Not Clickable")
WebDriverWait(driver, 15).until(EC.element_to_be_clickable((By.XPATH, "//BUTTON[#type='submit'[text()='Zum Warenkorb hinzufügen']"))).click()
WebDriverWait(driver, 150).until(EC.element_to_be_clickable((By.CLASS_NAME, "c-modal__content")))
I am not sure if your use of uppercase button is correct. Use the same syntax as in html.
One more thing: check your xpath with text():
It should be: //button[#type='submit' and text()='Zum Warenkorb hinzufügen']
Also, the general case for such loop in the case of one element is:
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By
from selenium.common.exceptions import TimeoutException
wait = WebDriverWait(driver, 15)
while True:
try:
element = wait.until(EC.element_to_be_clickable((By.XPATH, "//button[#type='submit' and text()='Zum Warenkorb hinzufügen']")))
print("clickable")
element.click()
except TimeoutException:
break
So im trying to figure out how to run this loop properly, my issue is that depending on the link that is loading, the page that loads will have an access denied error, this isnt like that for all the links, my issue is that i would like to identify whether or not when a particular element loads onto my screen, the program recognizes it and breaks the loop, and starts the next iteration in the for loop, so im trying to determine whether the "Access-Denied" element is present, and if it is, then break, otherwise, continue the for loop
idList = ["8573", "85678", "2378", "2579"]
for ID in idList:
print(ID)
driver.get(f"https://www.someWebsite/username/{ID}")
element = driver.find_element_by_class_name("Access-Denied")
print("error loading website")
break
if not element:
print("you may continue the for loop")
Mind you if the element showing the access denied page isnt present, i get an error that the 'Access-denied' element doesnt exist, how can i fix this?
You want to wait for the webpage to receive the proper response. Using the following code, you can wait for the full response to load, and then take
appropriate action based on the outcome:
from selenium.webdriver.common.by import By
from selenium.common.exceptions import TimeoutException
from selenium.webdriver.support.ui import WebDriverWait
...
try:
_ = WebDriverWait(driver, 10).until(
EC.presence_of_element_located((By.CLASS_NAME, "Access-Denied"))
)
print("error loading website")
break
except TimeoutException:
print("you may continue the for loop")
...
So you want to loop through if the access denied is there then break.
wait = WebDriverWait(driver, 10)
idList = ["8573", "85678", "2378", "2579"]
for ID in idList:
print(ID)
driver.get(f"https://www.someWebsite/username/{ID}")
try:
element=wait.until(EC.presence_of_element_located((By.CLASS_NAME, 'Access-Denied')))
break
except:
continue
Import
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
I have read several articles on this site regarding around the StaleElementReferenceException and am aware that this error is caused by the element no longer being in the site's DOM. What I am trying to do is click the bottom links on this webpage in order to go on and see the next page's listings. I have tried a few ways around this exception being given to me, and haven't found any to work. Here is an example of the code I have tried, and what I thought it might accomplish.
driver = webdriver.Chrome(r'C:\Users\Hank\Desktop\chromedriver_win32\chromedriver.exe')
driver.get('https://steamcommunity.com/market/listings/440/Unusual%20Old%20Guadalajara')
from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.support.ui import WebDriverWait as wait
from selenium.webdriver.support.expected_conditions import presence_of_element_located
from selenium.webdriver.common.action_chains import ActionChains
from selenium.webdriver.support import expected_conditions as EC
from selenium.common.exceptions import StaleElementReferenceException
action = ActionChains(driver)
page_links = wait(driver, 10).until(EC.presence_of_all_elements_located((By.CSS_SELECTOR, '[class^=market_paging_pagelink]')))
try:
action.move_to_element(page_links[1]).click().perform()
except StaleElementReferenceException as Exception:
print("Exception received, trying again")
time.sleep(5)
page_links = wait(driver, 10).until(EC.presence_of_all_elements_located((By.CSS_SELECTOR, '[class^=market_paging_pagelink]')))
action.move_to_element(page_links[1]).click().perform()
I was hoping that this code segment would attempt to move to the element at the bottom, click it, or return the error message, and try again, succeeding the second time. Instead, the code simply throws the error again. If my question has already been answered, please direct me to the relevant link.
Thank you!
The approach I normally go for is to click Next page until the button gets disabled/invisible.
Here's a working example based on your page. You should obviously do whatever relevant in the while loop; I chose to capture prices for the sake of example.
url="https://steamcommunity.com/market/listings/440/Unusual%20Old%20Guadalajara"
driver.get(url)
next_button=wait(driver, 10).until(EC.presence_of_element_located((By.ID,'searchResults_btn_next')))
# capture the start value from "Showing x-xx of 22 results"
#need this to check against later
ref_val=wait(driver, 10).until(EC.presence_of_element_located((By.ID,'searchResults_start'))).text
while next_button.get_attribute('class') == 'pagebtn':
next_button.click()
#wait until ref_val has changed
wait(driver, 10).until(lambda driver: wait(driver, 10).until(EC.presence_of_element_located((By.ID,'searchResults_start'))).text != ref_val)
# ====== Do whatever relevant here =============================
page_num=wait(driver, 10).until(EC.presence_of_element_located((By.CSS_SELECTOR,'.market_paging_pagelink.active'))).text
print(f"Prices from page {page_num}")
prices = wait(driver, 10).until(EC.presence_of_all_elements_located(
(By.XPATH, ".//span[#class='market_listing_price market_listing_price_with_fee']")))
for price in prices:
print(price.text)
#================================================================
#get the new reference value
ref_val = wait(driver, 10).until(EC.presence_of_element_located((By.ID, 'searchResults_start'))).text