I want to know how it can refresh until the element is found, for some reason this code wont work, it just right through the loop.
while True:
try:
element = driver.find_elements_by_xpath('//button[text()="SIGN UP"]')
except NoSuchElementException:
driver.refresh()
else:
break
driver.find_element_by_xpath('//button[text()="SIGN UP"]')
print("FOUND")
I haven't used selenium before but I'm going to make a safe bet that if the driver doesn't find anything matching that xpath, it will simply return None. In other words, your code is still valid because element is simply a None, thus not raising the error. What you can do instead is use a while loop to keep refreshing until it finds the element. Adding this function to a separate thread or process wouldn't be a bad idea either in case you have other things happening in the main loop.
def retry_until_id_found(element_id, max_retries=100):
retries = 0
while not driver.find_element_by_xpath(element_id)
if retries <= max_retries:
time.sleep(3)
driver.refresh()
retries+=1
else:
print(f"ELEMENT {element_id} NOT FOUND")
return None
print(f"FOUND {element_id}")
return driver.find_element_by_xpath(element_id)
element = retry_until_id_found(r'//button[text()="SIGN UP"]')
I believe below logic will help you
`if(element.visible) //false
{
driver.refresh()
n = 5 // you can give end limit
for(i=0;i<n;i++)
{
if(element.visible) //true
{
driver.find_element_by_xpath('//button[text()="SIGN UP"]')
print("FOUND")
i=n; //break the loop
}
else
{
driver.refresh()
}
}
}`
Related
i wanna know if element appear then disappear i want to apply it in this code
i know that internet is back by a text appear when internet is gone or its back
except:
time.sleep(3)
if driver.find_element(By.CLASS_NAME, "KhLQZTRq").size['width'] != 0 :
print ('internet lost')
while True:
time.sleep(5)
if driver.find_element(By.CLASS_NAME, "KhLQZTRq").size['width'] == 0 :
print("internet back")
else:
continue
else:
print("nothing happen")
This is working fine:
if driver.find_element(By.CLASS_NAME, "KhLQZTRq").size['width'] != 0
and it print 'internet lost' when the the element appear
But this is not working:
if driver.find_element(By.CLASS_NAME, "KhLQZTRq").size['width'] == 0
i just want it to print " internet back " if the element is no longer present
If the element appears or disappears you could write
if driver.find_element(By.CLASS_NAME, "KhLQZTRq"):
It will return True if the element exists and False if it doesn't
Please suggest if Selenium has a good option to wait until text will be changed within an element.
Conditions:
Page is not autoreloaded
Element which text I need is dynamically reloaded
Time required for this data to be updated is unknown
Expected text is unknown. It is a timestamp.
I wrote a method which checks it every 1 second (or any time I set) and gets the value when it is changed.
But I think there may be some better options. I try to avoid using time.sleep, but in the current case this is the only option I came to.
Note, this text may change even after 5 minutes, so I will need to adjust the number of retries retries or time.sleep()
Also, I use print just for debugging.
def wait_for_text(driver):
init_text = "init text"
retry = 1
retries = 120
start_time = time.time()
while retry <= retries:
time.sleep(1)
field_text = driver.find_element_by_id("my_id").text
if field_text != init_text:
break
retry += 1
now = time.time()
total_time = now-start_time
print(f"Total time for text to change {total_time}")
print(f"Final field value: {field_text}")
You can do the thing like this:
driver.get("https://stackoverflow.com")
init_text = "Log in"
from selenium.webdriver.support.wait import WebDriverWait
waiter = WebDriverWait(driver=driver, timeout=120, poll_frequency=1)
waiter.until(lambda drv: drv.find_element_by_class_name("login-link").text != init_text)
print("Success")
driver.quit()
So you are basically waiting for an element stops being equal to a given value.
P.S. - You can test the snippet above by changing the button text in dev tools.
You can loop until the text change to value you want
def wait_for_text(driver):
init_text = "init text"
retry = 1
while(driver.find_element_by_id(".") != init_text ):
retry += 1
print(driver.find_element_by_id(".").text)
print("number of tries: " + retry)
In the case I am looping into a list, where for value msg_list = 0 it will execute action(0), usr). This action can fail for a determined user, I should choose aother user if it happens, perform all the actions related to the user
How can I do to repeat action[0] if it fails?
for msg in range(len(msg_list)):
# in this case msg = 0
usr = select_random_user()
multiple_actions_for(usr) # This are lots of code lines I don't want to repeat!!
try:
action(msg, usr)
more_actions(usr.related_stuff)
except Exception as e:
go_back_to(msg =0 instead of looping into msg=1) # this is what I want to do
How can I do to get that? Repeat the loop for msg = i instead of passing to msg = i + 1?
Put your code into the endless while-loop with exiting from it if try was successful:
for msg in range(len(msg_list)):
while True:
usr = select_random_user()
multiple_actions_for(usr)
try:
action(msg, usr)
more_actions(usr.related_stuff)
except Exception as e:
continue
else:
break
It really depends. Is it okay to go back to the beginning of the loop? If so, you can call "continue", which stops the current iteration, and restarts the loop. Otherwise, I don't think there's something similar to a goto in Python, no. It's a very structured language.
Try using while loop instead of for loop. The idea is as shown bellow:
bool still_looping = True
msg = 0
while still_looping:
usr = select_random_user()
multiple_actions_for(usr)
try:
action(msg, usr)
more_actions(usr.related_stuff)
if (msg < len (msg_list)):
msg += 1
except Exception as e:
# Do whatever you want here. msg was not incremented
if (msg == len(msg_list))
still_looping = False #verify if this was the last execution
I am trying to trigger an action when the number 1 appears on a web element, but how do I check for it?
This is what I am trying to do, and I get the error 'WebElement' is not iterable
def is_0(self):
nav = Chrome()
nav.set_window_size(1360, 760)
while True:
if 1 in nav.find_element_by_xpath('//*[#id="header"]/nav/ul/li[4]/a/span/b'):
break
else:
print('Verificando')
sleep(2)
In order to get a text of an element, you should use ".text" or ".get_attribute('innerHTML')". I used ".get_attribute('innerHTML')" in my code.
Please refer to my code.
def is_0(self):
nav = Chrome()
nav.set_window_size(1360, 760)
while True:
if '1' in nav.find_element_by_xpath('//*[#id="header"]/nav/ul/li[4]/a/span/b').get_attribute('innerHTML'):
break
else:
print('Verificando')
sleep(2)
I am trying to scrape a website and fairly new to Python. I have managed to come up with below code. The problem however is it goes into an infinite loop after reaching the last page i.e Next button is greyed out.
Also i don't think i am catching the Stale Element properly here. Any help would be greatly appreciated!`
pages_remaining = True
while pages_remaining:
button=driver.find_element_by_class_name("arrow-right")
href_data = button.get_attribute('href')
if href_data is not None:
soup=BeautifulSoup(driver.page_source,"html.parser")
data = soup.find_all("div",{"class":"shelfProductStamp-content row"})
count = 1
for item in data:
ProductText=item.find("a",attrs={"class":"shelfProductStamp-imageLink"})["title"]
if item.find("span",attrs={"class":"sf-pricedisplay"}) is not None:
Price=item.find("span",attrs={"class":"sf-pricedisplay"}).text
else:
Price=""
if item.find("p",attrs={"class":"sf-comparativeText"}) is not None:
SubPrice1=item.find("p",attrs={"class":"sf-comparativeText"}).text
else:
SubPrice1=""
if item.find("span",attrs={"class":"sf-regoption"}) is not None:
Option=item.find("span",attrs={"class":"sf-regoption"}).text
else:
Option=""
SubPrice=str(SubPrice1)+"-"+str(Option)
SaleDates=item.find("div",attrs={"class":"sale-dates"}).text
urll2=driver.current_url
PageNo=driver.find_element_by_class_name("current").text
writer.writerow([ProductText,Price,SubPrice,SaleDates,PageNo])
count+=1
try:
def find(driver):
element = driver.find_element_by_class_name("arrow-right")
if element:
return element
else:
pages_remaining=False
#driver.quit()
time.sleep(10)
driver.implicitly_wait(10)
element = WebDriverWait(driver, 60).until(find)
driver.execute_script("arguments[0].click();", element)
except StaleElementReferenceException:
pass
else:
break
Thanks
When you set pages_remaining = False inside the find() function, that is a local variable. It is not the same variable as pages_remaining in the outer loop.
If you want to do it that way, you'll need to make it a global.
Thanks for your help here. I managed to fix this by simply adding another if statement at the end and swapping the time.sleep(10) as below
try:
def find(driver):
element = driver.find_element_by_class_name("arrow-right")
if element:
return element
driver.implicitly_wait(10)
element = WebDriverWait(driver, 60).until(find)
driver.execute_script("arguments[0].click();", element)
time.sleep(10)
except StaleElementReferenceException:
pass
if href_data is None:
break