After drag-and-drop operations, Selenium (Python) sometimes refuses to budge - python

After some dragging and dropping of elements into one another, the my program sometimes hangs. So I have a timeout set for it that runs the first block of code when the timer is reached. It does print the first line, but Selenium refuses to budge as driver.close() does not run after the print statement, and the rest of the code is rendered unreachable. The whole program hangs and cannot proceed. Is this a bug with Selenium or something I wrote?
print("This took too long. Will run a different function.")
driver.close()
driver.switch_to_window(driver.window_handles[0])
sleep(2)
# REST OF CODE
Could it possibly be the drag-and-drop code?
if elementsToMove:
a1 = random.choice(elementsToMove)
a2 = random.choice(elementsToMove)
while a1 == a2:
a2 = random.choice(elementsToMove)
actions = webdriver.ActionChains(driver)
actions.drag_and_drop(a1, a2)
actions.perform()

Years later, I will answer my own question.
I cringe reading my old code. I should have used sample, not choice twice.
I'm pretty sure it was a geckodriver issue. I don't know what fixed it, but it did get fixed.

Related

Python loops, need some advice

i trying to create a small program usign python and i need some help about python loops.
this small program will automates a fairly boring repetitive task.
I use module : selenium, time and pyautogui
here is the piece of code that i want to repeat until it no longer finds a certain element on the web page :
btnOptions = driver.find_element(By.XPATH, "/html/body/div[1]/div/div[1]/div/div[5]/div/div/div[3]/div/div/div[1]/div[1]/div/div/div[4]/div[2]/div/div[2]/div[3]/div[1]/div/div/div/div/div/div/div/div/div/div/div[8]/div/div[2]/div/div[3]/div/div")
btnOptions.click()
time.sleep(1)
pyautogui.press("down", presses=10)
pyautogui.press("enter")
time.sleep(1)
btn_move = driver.find_element(By.XPATH, "/html/body/div[1]/div/div[1]/div/div[6]/div/div/div[1]/div/div[2]/div/div/div/div/div/div/div[3]/div/div/div/div[1]")
btn_move.click()
as long as the btn_option is found, the program must continue otherwise it must stop.
I can't find a solution, if anyone can help me it would be very appreciated.
thanks a lot
i tried several loops but every time i get an error of course, I'm just new to coding in python :/
I've done a similar task. You may try this:
while True:
try:
btnOptions = driver.find_element(By.XPATH, "/html/body/div[1]/div/div[1]/div/div[5]/div/div/div[3]/div/div/div[1]/div[1]/div/div/div[4]/div[2]/div/div[2]/div[3]/div[1]/div/div/div/div/div/div/div/div/div/div/div[8]/div/div[2]/div/div[3]/div/div")
btnOptions.click()
time.sleep(1)
pyautogui.press("down", presses=10)
pyautogui.press("enter")
time.sleep(1)
btn_move = driver.find_element(By.XPATH, "/html/body/div[1]/div/div[1]/div/div[6]/div/div/div[1]/div/div[2]/div/div/div/div/div/div/div[3]/div/div/div/div[1]")
btn_move.click()
except NoSuchElementException:
break

Python multiprocessing process hangs at the end of it

I have a python script driving me crazy.
Right now i have a infinite loop that checks a data and get into a function in a specific situation.
while true:
time.sleep(1)
peso = getPeso()
if peso > 900:
processo = multiprocessing.Process(target=processo_automatico)
processo.start()
processo.join()
andare() #this is where it should go after the process.
The function works a lot of times but nondeterministically it hangs at the end of the process (literally finish and hangs there forever. How do i know this? i tried with logs).
So at the beginning I tried to terminate it with exit codes:
processo.join(timeout=10)
if processo.exitcode is None:
errore_cicalino() #this is just a warning for me
processo.kill()
elif processo.exitcode != 0:
errore_cicalino()
processo.kill()
but this never worked. NEVER.
So i tried without the join(). Tried with is_alive().
time.sleep(10)
if processo.is_alive():
processo.terminate()
errore_cicalino()
and even like this, it never entered this if.
This is driving me crazy, i accept the fact that the process could fail but, after the timeout, i should be able to terminate it and carry on with the script.
The script is running on a Raspberry Pi 4 2 GB.
Any idea?
Minimal example:
while True:
time.sleep(10)
processo = multiprocessing.Process(target=processo_automatico)
processo.start()
processo.join()
code randomly hangs at the end of the started process and cannot terminate in any way.
processo_automatico() is a function where the script get a picture from a camera and upload it in a DB thanks to another module.
def processo_automatico():
now = str(datetime.now())
now = now.replace(":", "-")
foto = CAMERA.read_camera()
cv2.imwrite("/var/www/html/" + now + ".png", foto)
DB.insert("/var/www/html/" + now + ".png", peso)
They don't create exceptions and i already tried to add to the end of the function a log info(executed even when the code hangs)
Solved.
What was that?
Well, my focus was on the end of the process while the issue was right at the start.
See the function getPeso()? That one just gets values from the serial.
After a few hours of getting those values the raspberry py just starts to see random values and you gotta reboot to fix it.
I wasn't prepared for that. My function just became a recursive infinite function with no break.
My tip, do not use infinite cycles except if you really need to or at least think if it could get stuck somewhere and check it.

Selenium Python Instagram Scraping All Images in a post not working

I am writing a small code to download all images/videos in a post. Here is my code:
import urllib.request as reqq
from selenium import webdriver
import time
browser = webdriver.Chrome("D:\\Python_Files\\Programs\\chromedriver.exe")
browser.get(url)
browser.maximize_window()
url_list = ['https://www.instagram.com/p/CE9CZmsghan/']
img_urls = []
vid_urls = []
img_url = ""
vid_url = ""
for x in url_list:
count = 0
browser.get(x)
while True:
try:
elements = browser.find_elements_by_class_name('_6CZji')
elements[0].click()
time.sleep(1)
except:
count+=1
time.sleep(1)
if count == 2:
break
try:
vid_url = browser.find_element_by_class_name('_5wCQW').find_element_by_tag_name('video').get_attribute('src')
vid_urls.append(vid_url)
except:
img_url = browser.find_element_by_class_name('KL4Bh').find_element_by_tag_name('img').get_attribute('src')
img_urls.append(img_url)
for x in range(len(img_urls)):
reqq.urlretrieve(img_urls[x],f"D:\\instaimg"+str(x+1)+".jpg")
for x in range(len(vid_urls)):
reqq.urlretrieve(vid_urls[x],"D:\\instavid"+str(x+1)+".mp4")
browser.close()
This code extracts all the images in the post except the last image. IMO, this code is right. Do you know why this code doesn't extract the last image? Any help would be appreciated. Thanks!
Go to the URL that you're using in the example and open the inspector, and very carefully watch how the DOM changes as you click between images. There are multiple page elements with class KL4Bh because it tracks the previous image, the current image, and the next image.
So doing find_element_by_class_name('KL4Bh') returns the first match on the page.
Ok, lets break down this loop and see what is happening:
first iteration
page opens
immediately click 'next' to second photo
grab the first element for class 'KL4Bh' from the DOM
the first element for that class is the first image (now the 'previous' image)
[... 2, 3, 4 same as 1 ...]
fifth iteration
look for a "next" button to click
find no next button
`elements[0]` fails with index error
grab the first element for class 'KL4Bh' from the DOM
the first element for that class is **still the fourth image**
sixth iteration
look for a "next" button to click
find no next button
`elements[0]` fails with index error
error count exceeds threshold
exit loop
try something like this:
n = 0
while True:
try:
elements = browser.find_elements_by_class_name('_6CZji')
elements[0].click()
time.sleep(1)
except IndexError:
n=1
count+=1
time.sleep(1)
if count == 2:
break
try:
vid_url = browser.find_elements_by_class_name('_5wCQW')[n].find_element_by_tag_name('video').get_attribute('src')
vid_urls.append(vid_url)
except:
img_url = browser.find_elements_by_class_name('KL4Bh')[n].find_element_by_tag_name('img').get_attribute('src')
img_urls.append(img_url)
it will do the same thing as before, except since it's now using find_elements_by_class and indexing into the resulting list, when it gets to the last image the index error for the failed button click will also cause the image lookup to increment the index it uses. So it will take the second element (the current image) on the last iteration of the loop.
There are still some serious problems with this code, but it does fix the bug you are seeing. One problem at a time :)
Edit
A few things that I think would improve this code:
When using try-except blocks to catch exceptions/errors, there are a few rules that should almost always be followed:
Name specific exceptions & errors to handle, don't use unqualified except. The reason for this is that by catching every possible error, we actually suppress and obfuscate the source of bugs. The only legitimate reason to do this is to generate a custom error message, and the last line of the except-block should always be raise to allow the error to propagate. It goes against how we typically think of software errors, but when writing code, errors are your friend.
The try-except blocks are also problematic because they are being used as a conditional control structure. Sometimes it seems easier to code like this, but it is usually a sign of incomplete understanding of the libraries being used. I am specifically referring to the block that is checking for a video versus an image, although the other one could be refactored too. As a rule, when doing conditional branching, use an if statement.
Using sleep with selenium is almost always incorrect, but it's by far the most common pitfall for new selenium users. What happens is that the developer will start getting errors about missing elements when trying to search the DOM. They will correctly conclude that it is because the page was not full loaded in the browser before selenium tried to read it. But using sleep is not the right approach because just waiting for a fixed time makes no guarantee that the page will be fully loaded. Selenium has a built-in mechanism to handle this, called explicit wait (along with implicit wait and fluent wait). Using an explicit wait will guarantee that the page element is visible before your code is allowed to proceed.

Try statement inside loop not being executed after first pass when exception thrown

I'm having selenium grab a url that is occasionally flaky in that the page doesn't load, so I want selenium to try the url again. Similar to a user clicking on a link that hangs the first time, so they click it again.
My issue is when the first "driver.get" doesn't work, it throws the TimeoutException, goes back to the top of the loop and instead of "try"ing again, it runs through the loop and exits the loop. Can someone shed some light on this? Please and thank you. :)
Some additional notes: I only get one "Timed out" print, so it seems the try statement is only being executed once. I get all five numbers from my iterator printed.
driver2.set_page_load_timeout(6)
for k in range(0, 5, +1):
print k
try:
driver2.get(url)
except TimeoutException:
print "Timed out"
Nothing is wrong with the above question. Only the fact that I wasn't checking success of the "driver.get()" which was apparently succeeding every subsequent pass.

Make a PyWinAuto Program wait for a popup with Python

I've got a Python 2.7 script that uses PyWinAuto to automate an application. At one point in the application, it goes off and does something for a long time...sometimes 15 seconds, sometimes up to 2 minutes...You never know...each time is different.
Once the process is finished, a popup appears, and I want PyWinAuto to continue on. So, I'm trying to make the program wait and check if that popup dialog has appeared. When it does, I try to break out of the loop. Here's a look at the code that does what I'm describing:
all_done = 1
while all_done != 1:
try:
app.Phazer.Static2.Texts() == [u'Would you like to Store Results?']
all_done = 1
break
except:
print("Testing...")
time.sleep(2)
..rest of the code..
However, 80% of the time, it works every time....Otherwise, PyWinAuto sometimes jumps out of the loop and tries to work on the popup dialog that hasn't appeared yet.
I'm new to Python, but I know there has to be a smarter, more reliable way to pull this off....Any ideas?
The only case I can imagine is that app.Phazer.Static2 is matched with another control sometimes.
app.Phazer.Static2 is equivalent to app.Phazer.ChildWindow(best_match='Static2'). Best match algorithm used in pywinauto can capture another static text with similar name.
Comparison operator == does't raise any exception, so you may get incorrect static text, it will return False to nothing, all_done = 1, break. That's it.
You can make the following code to make sure you connected with appropriate control:
app.Phazer.ChildWindow(class_name='Static', ctrl_index=1)
or
app.Window_(title='Phazer', class_name='#32770').ChildWindow(class_name='Static', ctrl_index=1)
if you're in doubt with capturing dialog.
And so the final check should be
if app.Phazer.ChildWindow(class_name='Static', ctrl_index=1).Texts() != [u'Would you like to Store Results?']:
raise Exception()

Categories

Resources