Reputation: 3082
How do I make selenium elements click faster?
I have written this script:
import os
import time
from selenium import webdriver
from selenium.webdriver.common import keys
from selenium.webdriver.common.action_chains import ActionChains
from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
def bot(url, mode=0):
Firefox.get(url)
time.sleep(3)
wait = WebDriverWait(Firefox, 3)
wait.until(EC.visibility_of_element_located((By.ID, 'start')))
wait.until(EC.element_to_be_clickable((By.ID, 'start')))
if mode in [0, 1]:
if Firefox.find_element_by_xpath('//*[text() = "30"]').get_attribute('class') != 'sp_cur':
wait.until(EC.element_to_be_clickable((By.XPATH, '//*[text() = "30"]'))).click()
Firefox.find_element_by_id('start').click()
wait.until(EC.visibility_of_element_located((By.XPATH, '//*[@id="clickarena"]')))
end = time.time() + 30
actions = ActionChains(Firefox)
button = Firefox.find_element_by_id('clickarena')
while time.time() < end:
if mode == 0:
button.click()
# actions.click(button).perform()
# Firefox.execute_script('document.getElementById("clickarena").click();')
elif mode == 1:
Firefox.find_element_by_tag_name('body').send_keys(Keys.SPACE)
elif mode == 2:
Firefox.find_element_by_id('start').click()
count = 50
while count:
button = Firefox.find_element_by_xpath('//*[@class = "apm-mark" and text() = {0}]'.format(str(count)))
button.click()
count -= 1
elif mode == 3:
Firefox.find_element_by_id('start').click()
words = ''
end = time.time() + 120
body = Firefox.find_element_by_tag_name('body')
left = Firefox.find_element_by_class_name('left-words')
while time.time() < end:
word = left.find_element_by_class_name('word').text
words += word
for i in word:
body.send_keys(i)
time.sleep(0.04)
words += ' '
body.send_keys(Keys.SPACE)
time.sleep(0.04)
with open(os.environ['USERPROFILE'] + '/Desktop/quotes.txt', mode='a+') as f:
print(words, file=f)
elif mode == 4:
Firefox.find_element_by_id('start').click()
body = Firefox.find_element_by_tag_name('body')
count = 0
while count < 5:
if body.get_attribute('class') == 'arealman r8status-splash':
body.click()
while (body.get_attribute('class') in ['arealman r8status-splash', 'arealman r8status-waiting']):
pass
if body.get_attribute('class') == 'arealman r8status-go':
body.click()
while body.get_attribute('class') != 'arealman r8status-result':
pass
body.click()
count += 1
if __name__ == '__main__':
Firefox = webdriver.Firefox()
bot('https://www.arealme.com/click-speed-test/en/')
time.sleep(1)
Firefox.switch_to.alert.accept()
time.sleep(7)
bot('https://www.arealme.com/spacebar-test/en/', 1)
time.sleep(1)
Firefox.switch_to.alert.accept()
time.sleep(7)
bot('https://www.arealme.com/apm-actions-per-minute-test/en/', 2)
time.sleep(7)
bot('https://www.arealme.com/typing-test/en/', 3)
time.sleep(7)
bot('https://www.arealme.com/reaction-test/en/', 4)
And the CPS & APM test results aren't impressive:
CPS:
APM:
At first I thought it is latency bound, I am in China behind the infamous GFW and using a VPN, so I pinged the website:
PS C:\Windows\System32> ping www.arealme.com
Pinging www.arealme.com [172.67.69.35] with 32 bytes of data:
Reply from 172.67.69.35: bytes=32 time=182ms TTL=58
Reply from 172.67.69.35: bytes=32 time=178ms TTL=58
Reply from 172.67.69.35: bytes=32 time=182ms TTL=58
Reply from 172.67.69.35: bytes=32 time=179ms TTL=58
Ping statistics for 172.67.69.35:
Packets: Sent = 4, Received = 4, Lost = 0 (0% loss),
Approximate round trip times in milli-seconds:
Minimum = 178ms, Maximum = 182ms, Average = 180ms
PS C:\Windows\System32> 1000/180
5.55555555555556
The number seemed to indicate mouse clicks are indeed latency bound.
However it doesn't explain the spacebar test result:
It is significantly faster than the mouse clicks.
So how can I increase mouse clicks per second of Python selenium webdriver?
I have Googled for a solution that clicks faster using many different keywords, and I will spare you the details, I have only found the two commented methods.
The first commented method is subjectively as slow as e.click()
, and the second commented line simply does nothing, I admit I am not well versed in javascript, but that line is what I have found on the website where I found it.
How can I increase mouse clicks per second of Python selenium, or is there a more performant library than selenium that is very similar to selenium?
Upvotes: 3
Views: 2133
Reputation: 193308
You want to make the Python-Selenium clicks faster? Here's a 407.0km/h / 252.9mph CPS falcon for you:
Code Block:
driver = webdriver.Chrome(service=s, options=options)
driver.get('https://www.arealme.com/click-speed-test/en/')
WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.XPATH, "//span[text()='Start']"))).click()
click_me = WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.CSS_SELECTOR, "button#clickarena>b")))
while True:
try:
click_me.click()
continue
except:
break
time.sleep(10) # result calculation
driver.save_screenshot("falcon.png")
Screenshot taken:
Whilest an APM Score of 2342
Code Block:
driver = webdriver.Chrome(service=s, options=options)
driver.get('https://www.arealme.com/apm-actions-per-minute-test/en/')
driver.execute_script("return arguments[0].scrollIntoView(true);", WebDriverWait(driver, 20).until(EC.visibility_of_element_located((By.XPATH, "//h6[contains(., 'Challenge')]"))))
driver.execute_script("arguments[0].click();", WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.XPATH, "//button[@id='start']//span[text()='Start']"))))
for i in range(50, 0, -1):
WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.XPATH, "//b[text()='{}']".format(str(i))))).click()
time.sleep(10) # result calculation
driver.save_screenshot("APMTEST.png")
Screenshot taken:
Upvotes: 4
Reputation: 177
It makes sense that it is not a web latency issue with this website, as the webdriver has already loaded the source from the remote server by the time your bot starts executing. The fact that you can ping the server with low latency suggests that the website executes exclusively within the browser while measuring your click rates (as opposed to processing the click and storing it in a remote database, for example).
The click
and send_keys
functions in Selenium are implemented in a relatively straightforward manner -- they execute the Javascript command to click or send the text to the webelement respectively. Seeing as the code is in Python (and, as such, scripted), the bot must wait for each line to fully execute and receive a response from the command before moving onto the next line. What you've found is that the response time from the click function is much slower than the send keys function.
There are multiple ways to get around this issue. For example, you can launch click commands in parallel with multiprocessing or subprocesses.
Upvotes: 1