When we create automated bots to do stuff for us on the internet, we are usually doing this for a reason. The reason may be to get some cash, data, or something like that. Usually, these sites may have protection from automated programs. If we would use the click()
default Selenium function, we would click virtually on the center of an object. It's easy to track or protect from such clicks. But if we would create a function that could click as a human, no one could say that we are using the bot. So in this short tutorial, I will create a virtual click function.
Continuing from the last tutorial, I modified two functions. At first, where we are starting a new Browser, I added an option to open a Chrome browser when we use "2" as an option. "1" is Firefox as before and "3" is no for custom browsers:
def StartBrowser(browser=1, browser_location='', driver_path=''):
if browser == 1:
driver = webdriver.Firefox()
if browser == 2:
driver = webdriver.Chrome()
if browser == 3:
options = webdriver.ChromeOptions()
options.binary_location = browser_location
driver = webdriver.Chrome(executable_path=driver_path, chrome_options=options)
#driver.implicitly_wait(30)
#driver.set_window_size(1920,1080)
#driver.maximize_window()
return driver
Our 3rd tutorial part had a quite simple function for opening new tabs, so I added more functionality for more advanced users. This new function can choose to what window we will switch after the new tab opens. There is protection not to hang if our new tab opens only a blank page (possible when the link doesn't work). And you can add functionality if our function opens a wrong link or opened link redirects you somewhere else:
def NewTab(driver, Link, default_page=0, custom=0):
window_count = len(driver.window_handles)
driver.execute_script('''window.open("'''+Link+'''","_blank");''')
while len(driver.window_handles) != window_count+1:
time.sleep(0.5)
if custom == 0:
driver.switch_to.window(driver.window_handles[-1])
if custom != 0:
driver.switch_to.window(driver.window_handles[custom])
time.sleep(2)
if driver.current_url == Link:
current_window = driver.current_window_handle
return current_window
if driver.current_url == "about:blank":
time.sleep(2)
DriverClose()
driver.switch_to.window(driver.window_handles[default_page])
print("current window was about:blank we closed it, trying again in 10s")
time.sleep(10)
NewTab(driver, Link, default_page, custom)
if driver.current_url != Link:
pass
Here comes the final VirtualClick function we are creating. At first, let's import random
library along with other imports. In the next tutorial, I will not explain exceptions. I am doing this in the video tutorial. We can choose we will use random object coordinates click in this function, or we'll always click in the center.
Here is the simplified function version, but if you use it, you will face errors quite soon(not recommended to use):
def VirtualClick(driver, click_object):
size = click_object.size
height_rand = random.randint(1,int(sizeList[0])-1)
width_rand = random.randint(1,int(sizeList[1])-1)
action = webdriver.common.action_chains.ActionChains(driver)
action.move_to_element_with_offset(click_object, width_rand, height_rand)
action.click()
action.perform()
return True
So our original function does the same as the simplified version above. But we integrated exceptions to protect from errors. If we would try to find out what our code does above, so at the first line, it gets x and y size of HTML object. In the next two lines, it picks random height_rand and width_rand coordinates. It's random coordinates which are between 1-x and 1-y axis. In the next line, we are using the standard ActionChains function to do everything like a human. Then we are moving our mouse to our chosen random coordinates and performing the virtual click()
function. At the last line of code, we return True if everything is fine there.
So bellow is the same code we'll use in our further coding, where we handle exceptions:
def VirtualClick(driver, click_object, UseRandom=True):
try:
size = click_object.size
except StaleElementReferenceException:
print("StaleElementReferenceException")
return False
sizeList = list(size.values())
height = int(sizeList[0])-1
width = int(sizeList[1])-1
if UseRandom == True:
try:
height_rand = random.randint(1,height)
except ValueError:
height_rand = 1
try:
width_rand = random.randint(1,width)
except ValueError:
width_rand = 1
if UseRandom == False:
height_rand = height
width_rand = width
action = webdriver.common.action_chains.ActionChains(driver)
try:
action.move_to_element_with_offset(click_object, width_rand, height_rand)
except StaleElementReferenceException:
return False
action.click()
try:
action.perform()
except MoveTargetOutOfBoundsException:
print("MoveTargetOutOfBoundsException with action.perform()")
return False
except StaleElementReferenceException:
print("StaleElementReferenceException with action.perform()")
return False
return True
And here comes the final up to date code:
from selenium import webdriver
import time
from selenium.webdriver import ActionChains
from selenium.webdriver.common.keys import Keys
from selenium.common.exceptions import WebDriverException
from selenium.common.exceptions import NoSuchElementException
from selenium.common.exceptions import NoSuchFrameException
from selenium.common.exceptions import NoSuchWindowException
from selenium.common.exceptions import ElementNotInteractableException
from selenium.common.exceptions import StaleElementReferenceException
from selenium.common.exceptions import MoveTargetOutOfBoundsException
from selenium.common.exceptions import UnexpectedAlertPresentException
from selenium.common.exceptions import ElementClickInterceptedException
from selenium.common.exceptions import JavascriptException
import random
def CheckExistsById(driver, CheckId):
try:
DriverId = driver.find_element_by_id(CheckId)
except NoSuchWindowException:
return False
return DriverId
def CheckExistsByName(driver, CheckName):
try:
DriverName = driver.find_element_by_name(CheckName)
except NoSuchWindowException:
return False
return DriverName
def CheckExistsByXpath(driver, xpath):
try:
path = driver.find_element_by_xpath(xpath)
except NoSuchWindowException:
return False
except WebDriverException:
return False
except StaleElementReferenceException:
return False
return path
def CheckExistsArrayByXpath(driver, xpath):
try:
path = driver.find_elements_by_xpath(xpath)
except NoSuchWindowException:
return False
except WebDriverException:
return False
except StaleElementReferenceException:
return False
return path
def MinimizeWindow(driver):
try:
driver.minimize_window()
except UnexpectedAlertPresentException:
return False
return True
def DriverClose(driver):
try:
driver.close()
except NoSuchWindowException:
print("NoSuchWindowException in driver.close()")
return False
return True
def SimpleClick(driver, ObjectToClick):
try:
ObjectToClick.click()
except ElementNotInteractableException:
return False
except ElementClickInterceptedException:
return False
except TypeError:
return False
return True
def StartBrowser(browser=1, browser_location='', driver_path=''):
if browser == 1:
driver = webdriver.Firefox()
if browser == 2:
driver = webdriver.Chrome()
if browser == 3:
options = webdriver.ChromeOptions()
options.binary_location = browser_location
driver = webdriver.Chrome(executable_path=driver_path, chrome_options=options)
#driver.implicitly_wait(30)
#driver.set_window_size(1920,1080)
#driver.maximize_window()
return driver
def NewTab(driver, Link, default_page=0, custom=0):
window_count = len(driver.window_handles)
driver.execute_script('''window.open("'''+Link+'''","_blank");''')
while len(driver.window_handles) != window_count+1:
time.sleep(0.5)
if custom == 0:
driver.switch_to.window(driver.window_handles[-1])
if custom != 0:
driver.switch_to.window(driver.window_handles[custom])
time.sleep(2)
if driver.current_url == Link:
current_window = driver.current_window_handle
return current_window
if driver.current_url == "about:blank":
time.sleep(2)
DriverClose()
driver.switch_to.window(driver.window_handles[default_page])
print("current window was about:blank we closed it, trying again in 10s")
time.sleep(10)
NewTab(driver, Link, default_page, custom)
if driver.current_url != Link:
pass
def VirtualClick(driver, click_object, UseRandom=True):
try:
size = click_object.size
except StaleElementReferenceException:
print("StaleElementReferenceException")
return False
sizeList = list(size.values())
height = int(sizeList[0])-1
width = int(sizeList[1])-1
if UseRandom == True:
try:
height_rand = random.randint(1,height)
except ValueError:
height_rand = 1
try:
width_rand = random.randint(1,width)
except ValueError:
width_rand = 1
if UseRandom == False:
height_rand = height
width_rand = width
action = webdriver.common.action_chains.ActionChains(driver)
try:
action.move_to_element_with_offset(click_object, width_rand, height_rand)
except StaleElementReferenceException:
return False
action.click()
try:
action.perform()
except MoveTargetOutOfBoundsException:
print("MoveTargetOutOfBoundsException with action.perform()")
return False
except StaleElementReferenceException:
print("StaleElementReferenceException with action.perform()")
return False
return True
browser_location = "C:/Users/HOME/Desktop/chrome-win/chrome.exe"
driver_path = "C:/Users/HOME/Desktop/chrome-win/chromedriver.exe"
driver = StartBrowser(1, browser_location, driver_path)
time.sleep(1)
driver.get("https://www.google.com")
time.sleep(1)
NewTab(driver, "https://www.google.com/gmail/about/new/")
signin = CheckExistsByXpath(driver, "//a[starts-with(.,'Sign In')]")
VirtualClick(driver, signin)
time.sleep(0.5)
driver.switch_to.window(driver.window_handles[-1])
time.sleep(2)
email = CheckExistsByXpath(driver, "//input[@type='email']")
email.send_keys("email")
next = CheckExistsByXpath(driver, "//span[@class='RveJvd snByac']")
VirtualClick(driver, next)
So now we have quite a nice function pack to use in our coding. You can use them for your own purposes or test this code. I wrote a simple example, which may be used to log in to a Gmail account. But this code not always works because Gmail usually changes his login page HTML code, so if it doesn't work, you'll need to adapt it. Another way you can continue on this tutorial series where you will find more interesting stuff on selenium.