How to know scroll bar is at end in selenium python - python

I am implementing a while loop in selenium, and want to condition my while loop, so when the scroll bar is at its end of its scroll the while loop should stop. How can i code this type of condition in while loop?
Iam using Keys.DOWN and my while loop is right now set to True
My code of while loop:
while True:
self.driver.find_element_by_id('pane-side').send_keys(Keys.DOWN * 5)
self.driver.find_elements_by_xpath("//div[#class='_2wP_Y']")

Here is the pseudo code that should do the trick.
Check if the current (scrolled position+ window height) is greater than page height(-1)
pageHeight = driver.execute_script("return document.body.scrollHeight")
totalScrolledHeight = driver.execute_script("return window.pageYOffset + window.innerHeight")
# -1 is to make sure the rounding issues
if((pageHeight-1)<=totalScrolledHeight):
print("pass")
else:
print("Failed")

I think this will work for you.
It checks if the new height is greater than the previous height. If it's True, it will continue. Else, it will break the loop.
pre_height = 0
new_height = 0
while True:
time.sleep(1)
self.driver.execute_script("window.scrollBy(0, 5000);")
new_height = self.driver.execute_script("return document.body.scrollHeight")
if pre_height < new_height:
print('once again')
pre_height = self.driver.execute_script("return document.body.scrollHeight")
else:
print("maybe finished?")
break

Set the condition of the while loop to check if the position of the scroll bar is at the lowest point possible.

Related

Why is my nested while loop not working? if and second while loop is expected

the program should search for a image in the first loop and add it to a list, in the secon loop should he search till he find a image that isnt already in the list. PyCharm give me the errors that while search = True: and if pic == used is expected.
used = []
search = True
#First Loop
while True:
pic = driver.find_element(By.CSS_SELECTOR,value=".image-post img")
time.sleep(2)
pic_url = pic.get_attribute("src")
pic_title = pic.get_attribute("alt")
used.append(pic)
time.sleep(200)
#Second loop
while search = True:
pic = driver.find_element(By.CSS_SELECTOR, value=".image-post img")
if pic == used
search = True
else:
search = False
used.append(pic)
...
Try this
used = []
#First Loop
while True:
search = True #moved search = True here so that the nested loop will run each iteration of the main loop as it will be set back to True
pic = driver.find_element(By.CSS_SELECTOR,value=".image-post img")
time.sleep(2)
pic_url = pic.get_attribute("src") #you’re not doing anything with this from the looks of it
pic_title = pic.get_attribute("alt") #same with this
used.append(pic)
time.sleep(200)
#Second loop
while search:
pic = driver.find_element(By.CSS_SELECTOR, value=".image-post img")
if pic != used:#may want to change “used” to “used[-1]” here as used is a list while it appears pic is not, so the -1 will get the last value in used
search = False
used.append(pic)
You could also replace search with True and change the “search = False” with “break”
I think that you used a bad operator type. By that, I mean that you should probably use == and not =.
Check it and inform me.

Cannot locate child element Selenium

Trying to pick out single restaurant elements under the All Restaurants category on this page. https://www.foodpanda.sg/restaurants/new?lat=1.2915902&lng=103.8379066&vertical=restaurants
All li elements have a different class name. The only working xpath, I have been able to figure out is this one.
//ul[#class="vendor-list"]//li[3]
I cannot figure out how to increase this number and get all the restaurants, which is complicated by the fact that there is an infinite scroll as well.
j = 1
def get_rest():
global j
while True:
driver.execute_script("window.scrollBy(0,2525)", "")
time.sleep(5)
var = f'{[j]}'
elems = driver.find_elements_by_xpath(f'//ul[#class="vendor-list"]//li{var})
return elems
I guess it should be something like this
all_restaurants = set()
restaurant_locator = '//ul[#class="vendor-list"]//li[#data-testid and not(#class)]'
page_bottom_locator = '.restaurants__city-bottom-info'
while #bottom is not reached:
restaurants = driver.find_elements_by_xpath(restaurant_locator)
all_restaurants.add(restaurants)
time.sleep(1)
driver.execute_script("window.scrollTo(0, document.body.scrollHeight);")
I tried to get the innerHTML of the //ul[#class="vendor-list"]//li
Code :
driver.get("https://www.foodpanda.sg/restaurants/new?lat=1.2915902&lng=103.8379066&vertical=restaurants")
while True:
for item in driver.find_elements(By.XPATH, "//ul[#class='vendor-list']/li"):
ActionChains(driver).move_to_element(item).perform()
sleep(0.1)
print(item.get_attribute('innerHTML'))

In Python how would one wait a specific time while waiting for an image to possibly occur?

More specifically, I have a Sikuli code that works fine for the most part. However, during my 5400 second wait sometimes I have a network connection error that pops a button on the screen I need to click that occurs at no specific time during those 5400 seconds. Also, if that network button occurs and I click it I need to start the code over from the beginning.
I assume I can do a nested While loop waiting for that network connection button to pop up and if it doesn't occur continue with the code but how would I write that? Here's the code currently:
while True:
exists("start.png", 10*60)
click(Pattern("start.png").targetOffset(-1,0))
wait("enter.png", 5)
click(Pattern("enter.png").targetOffset(2,30), 5)
wait(5400)
type(Key.ESC)
exists("leave.png", 5)
click(Pattern("leave.png").targetOffset(-11,0))
#the following if statements could or could not occur and could come in no specific order. This part of the code could be incorrect
if exists("close1.png", 5):
click(Pattern("close1.png").targetOffset(0,1))
elif exists("close2.png", 20):
click("close2.png")
elif exists("close3.png", 20):
click("close3.png")
wait(5)
A suggestion from RaiMan from SikuliX (not tested ;-)
"""
#the following if statements could or could not occur and could come in no specific order.
#This part of the code could be incorrect
if exists("close1.png", 5):
click(Pattern("close1.png").targetOffset(0,1))
elif exists("close2.png", 20):
click("close2.png")
elif exists("close3.png", 20):
click("close3.png")
"""
netError = False
def handler(event):
global netError
netError = True
click(event.getMatch())
onAppear("close1.png", handler)
onAppear("close2.png", handler)
onAppear("close3.png", handler)
while True:
netError = False
observeInBackground(FOREVER)
#exists("start.png", 10*60)
#click(Pattern("start.png").targetOffset(-1,0))
click(wait("start.png", 1))
#wait("enter.png", 5)
#click(Pattern("enter.png").targetOffset(2,30), 5)
click(wait(Pattern("enter.png").targetOffset(2,30), 5)
towait = 5400
while not netError and toWait > 0:
wait(1)
towait -= 1
if netError:
stopObserver()
continue
type(Key.ESC)
#exists("leave.png", 5)
#click(Pattern("leave.png").targetOffset(-11,0))
click(wait(Pattern("leave.png").targetOffset(-11,0), 5)
stopObserver()
wait(5)
Here is some alternative without observer events. I personally find it simpler to work in this way :-).
I used your original code and just replaced wait(5400) with a time based loop that checks for images that might occur.
import time
while True:
exists("start.png", 10*60)
click(Pattern("start.png").targetOffset(-1,0))
wait("enter.png", 5)
click(Pattern("enter.png").targetOffset(2,30), 5)
t0 = time.time()
while (time.time()-t0 < 5400):
#the following if statements could or could not occur and could come in no specific order. This part of the code could be incorrect
if exists("close1.png", 5):
click(Pattern("close1.png").targetOffset(0,1))
elif exists("close2.png", 20):
click("close2.png")
elif exists("close3.png", 20):
click("close3.png")
type(Key.ESC)
exists("leave.png", 5)
click(Pattern("leave.png").targetOffset(-11,0))
wait(5)

Continue running a loop until a button is pressed using gpiozero - button press not registered

I have some python code on a raspberry pi that I want to run and carry on a loop until a button is pressed.
The button.wait_for_press() is not suitable because that pauses the program until it runs, but I have tried it out to see if the hardware is working and it does.
def shutterPressed():
global shutterHasBeenPressed
shutterHasBeenPressed = True
def main():
"""
Main program loop
"""
#start camera preview
camera.start_preview(resolution=(SCREEN_W, SCREEN_H))
#Display Intro screens
intro_image_1 = REAL_PATH + '/assets/intro_1.png'
intro_image_2 = REAL_PATH + '/assets/intro_2.png'
overlay_1 = overlay_image(intro_image_1, 0, 3)
overlay_2 = overlay_image(intro_image_2, 0, 4)
#Wait for button press
i = 0
blink_speed = 10
button.when_pressed = shutterPressed
while True:
global shutterHasBeenPressed
shutterHasBeenPressed = False
#Stay in loop until button is pressed
if shutterHasBeenPressed is False:
i += 1
if i == blink_speed:
overlay_2.alpha = 255
elif i == (2 * blink_speed):
overlay_2.alpha = 0
i = 0
#Restart while loop
sleep(0.1)
continue
#button has been pressed!
print("Button Pressed!")
When I run this code, the button press is not registered at all.
What have I got wrong?
EDIT: so I added a print statement to the shutterPressed() function and confirmed that it is running when the button is pressed.
In also added a statement to print the value of shutterHasBeenPressed just before the if statement. This never changed from false.
However, if I removed the line changing the variable to false at the beginning of the loop, then code worked, so it is obviously something to do with when various bits get run. Maybe the while loop starts again after the shutterPressed() function runs?
Either way, i have fixed it by moving the reassignment of the variable to after the if statement.
Welcome to the world of concurrency (somewhat)!
Just imagine your program running: the instructions are being executed one after the other in the order in which they are written, according to the execution flow that they define with the exception of shutterPressed which is asynchronously executed (maybe).
Therefore, imagine we enter the loop and are at the first line, <here>:
while True:
global shutterHasBeenPressed
shutterHasBeenPressed = False # <here>
#Stay in loop until button is pressed
if shutterHasBeenPressed is False:
i += 1
if i == blink_speed:
overlay_2.alpha = 255
elif i == (2 * blink_speed):
overlay_2.alpha = 0
i = 0
#Restart while loop
sleep(0.1)
continue
#button has been pressed!
print("Button Pressed!")
Now, shutterHasBeenPressed has been set to False and the condition that follows is verified so that we enter the if.
the program keeps running until, unexpectedly, the button is pressed. Say, it reached <here>:
while True:
global shutterHasBeenPressed
shutterHasBeenPressed = False
#Stay in loop until button is pressed
if shutterHasBeenPressed is False:
i += 1
if i == blink_speed:
overlay_2.alpha = 255 # <here>
elif i == (2 * blink_speed):
overlay_2.alpha = 0
i = 0
#Restart while loop
sleep(0.1)
continue
#button has been pressed!
print("Button Pressed!")
At this point, shutterPressed runs, sets shutterHasBeenPressed to True. Then, back in our loop, the iteration finishes, we continue at the start of the loop and ... what's there?!
shutterHasBeenPressed = False
and the button press just went completely unnoticed!
I believe this answers your question asking what you have got wrong.

how to wait for a specific command to finish in selenium

I'm trying to get some info from pages that look like this link to the site
I need to scroll all the way down, I wrote a function for that.
def Scroll():
startPos = driver.execute_script("return window.pageYOffset;")
while 1:
driver.execute_script("window.scrollTo(0, document.body.scrollHeight);") #need to wait
time.sleep(0.1)
newPos = driver.execute_script("return window.pageYOffset;")
if newPos == startPos:
break
startPos = newPos
return
I would like to change time.sleep(0.1) with some conditional wait until the line before that one is executed, is there a way to do this? There is no special element loaded after every scroll or at the end of the page.
Solution:
...
driver.execute_script("window.scrollTo(0, document.body.scrollHeight);")
while 1:
if driver.execute_script("return jQuery.active == 0"):
break
else:
time.sleep(0.05)
continue
...
Instead of thread.sleep, you can use following code which waits for Ajax calls to complete because every scroll, there will be a Ajax call in the background.
WebDriverWait wait=new WebDriverWait(driver, 120);
Wait.until(ExpectedConditions.jsReturnValue("return jQuery.active == 0"));

Categories

Resources