Selenium has a lot of actions, e.g., driver.find_element_by_xpath('XXX').click(), driver.find_element_by_xpath('XXX').send_keys(). I would like to add some features (e.g. random pause) to make them real (like humans).

Adding time.sleep() before each action is not Pythonic and takes too many lines (one line before an action). In addition, we want the pause time for different types of actions are different (send_keys(input_text) should be longer than click()).

I tried the following but failed:

from selenium.webdriver.common.action_chains import ActionChains

def pause_wrapper(func, min_time=0, max_time=None):
    """Before execute func, we pause some time [min_time, max_time]."""
    def wrapper(*args, **kwargs):
        pause_time = random.uniform(min_time, max_time)
        print(f'We are going to pause {pause_time} s.')
        time.sleep(pause_time)
        return func(*args, **kwargs)
    return wrapper

ActionChains.send_keys = pause_wrapper(ActionChains.send_keys, min_time=5, max_time=10)
ActionChains.click = pause_wrapper(ActionChains.click, min_time=1, max_time=3)

driver.find_element_by_xpath('XXX').send_keys(Keys.ENTER)

My questions are: 1. Why my method fails (no pause and no print result)? 2. How to approach it?


To clarify: I want to force hard pause, not the other around (as wrongly flagged as similar).

1 Answers

2
andreihondrari On

you could define a wait like:

from selenium.webdriver.support.ui import WebDriverWait
wait = WebDriverWait(driver_instance, 1000)

and then use it to perform certain waits like:

from selenium.common.exceptions import TimeoutException
from selenium.webdriver.support import expected_conditions as EC

wait.until(
    EC.url_contains("http://example.com")
)

do keep in mind that the wait will throw a TimeoutException after a while.

In some cases time.sleep is an acceptable solution.

More about the expected conditions can be consulted in the selenium documentation