Upload file using selenium, VirtualDisplay and dwm
2 min readMay 18, 2021
I use this approach when I can not simply change the value of the file input tag.
We will run it console, so we should use PyVirtualDisplay with window manager (I am using gdm, you can try fluxbox it is easy to install but need more RAM then gdm) and Xephyr for debug. To run window manager we will use EasyProcess
So we will call File Upload Dialog, by clicking on element or button, then we simulate send keys with pynput and all these running in our console.
import time
from easyprocess import EasyProcess
from pynput.keyboard import Key, Controller
from pyvirtualdisplay import Display
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
class ImageUploadAutomation:
def __init__(self, data_directory, screen_width, screen_height):
self.chrome_path = "path/to/chrome"
self.data_directory = data_directory
self.screen_width = screen_width
self.screen_height = screen_height
self.chrome_options = self._set_options()
self.driver = None
def _set_options(self):
chrome_options = Options()
chrome_options.add_argument("--no-sandbox")
chrome_options.add_argument("--disable-notifications")
chrome_options.add_argument("--disable-dev-shm-usage")
chrome_options.add_argument(
f"--window-size={self.screen_width},{self.screen_height}"
)
chrome_options.add_argument("--start-maximized")
chrome_options.add_argument(f"user-data-dir={self.data_directory}")
chrome_options.add_experimental_option(
"excludeSwitches", ["disable-popup-blocking"]
)
chrome_options.add_argument("--disable-blink-features=AutomationControlled")
return chrome_options
def upload(self, photo):
# Change visible to 1 if you want to use Xephyr debug
with Display(
visible=0, size=(self.screen_width, self.screen_height)
) as display:
with EasyProcess(["dwm"]) as process: self.driver = webdriver.Chrome(
executable_path=self.chrome_path,
chrome_options=self.chrome_options
)
keyboard = Controller()
url = "https://www.exmaple.com"
self.driver.get(url)
test = self.driver.find_element_by_xpath(
"//div[@aria-label='Add Photos']"
)
time.sleep(1)
test.click()
time.sleep(1)
for key in photo.path:
keyboard.press(key)
keyboard.release(key)
# keyboard.press(Key.enter)
with keyboard.pressed(Key.enter):
pass