When I set "options.headless = True", this fails because the EC condition is never met, as if the menus are not actually being clicked and the page title is not changing. When not in headless mode, this works absolutely fine and the EC condition is nicely met, implying the top level menu selections worked fine and took me to the right page.....
This is my first attempt at headless mode, but I am assuming it just builds a virtual dom, and so the navigation through the menus should take me to the same page, with the same title as non-headless?
class OrganizationsAutomate():
def __init__(self, driver:ERVAutomate):
self.driver=driver
def task_navigate_to_organizations(self):
print("Navigating to Organizations...")
print("Clicking Products menu...")
self.driver.ui.click_nav_menu(selector_type="CSS", selector_text="a.vv-navbar-link",
menu_name="Products", time_to_sleep=2)
print("Clicking Organizations menu...")
self.driver.ui.click_nav_menu(selector_type="CSS", selector_text="a.vv-navbar-link",
menu_name="Organizations", time_to_sleep=2)
try:
element = WebDriverWait(self.driver, 30).until(
EC.title_contains("Organizations")
)
except Exception as e:
print("Do not appear to be on the Organizations page....", e)
raise e
print("Navigated to Organizations....")
Update: I am having more luck by not maximising the window in Headless mode, and just setting a window size.
def __init__(self, driver_path, url, user_name, user_password, implicit_wait=5, teardown=False):
self.__driver_path = driver_path
self.__url = url
self.__user_name = user_name
self.__user_password = user_password
self.__implicit_wait = implicit_wait
self.__teardown = teardown
self.__ui = UIInteract(self)
# add the chrome drive to the path
os.environ['PATH'] += self.__driver_path
options = webdriver.ChromeOptions()
options.add_experimental_option('excludeSwitches', ['enable-logging'])
options.headless = True
options.add_argument("--disable-extensions")
options.add_argument("--disable-infobars")
options.add_argument("--window-size=1920,1080");
# initalise webdriver super class
super(ERVAutomate, self).__init__(options=options)
# implicit wait time for finding an element in selenium
self.implicitly_wait(self.__implicit_wait)
In headless mode, you can add below args to make it more stable.
options = webdriver.ChromeOptions()
options.add_argument("--headless")
options.add_argument("--start-maximized")
options.add_argument("--disable-extensions")
options.add_argument("--disable-infobars")
options.add_argument('--window-size=1920,1080')
driver = webdriver.Chrome(executable_path = driver_path, options = options)
or
driver = webdriver.Chrome(options = options)
also try to put some sleep or delay, having an explicit waits is a way to go with Selenium.
Also read here for more details.
You can try this argument as well as headless mode.
options.add_argument('--no-sandbox')
Related
I'm having troubles to debug why is firefox not working in headless mode. This is how I create the drivers:
def __get_firefox_options(headless=True) -> webdriver.FirefoxOptions:
"""
Get Firefox configuration
"""
options=webdriver.FirefoxOptions()
if headless == True:
options.headless = True
options.add_argument("window-size=1920x1080")
options.add_argument("--start-maximized")
options.add_argument("--disable-gpu")
return options
def __get_firefox_driver(drivers_path, headless) -> webdriver.Firefox:
"""
Return an instance of the geckodriver
"""
driver_path = os.path.join(drivers_path, 'geckodriver.exe')
service = FirefoxService(driver_path)
driver = webdriver.Firefox(
service=service,
options=__get_firefox_options(headless=headless)
)
driver.maximize_window()
return driver
And chrome:
def __get_chrome_options(headless=False) -> webdriver.ChromeOptions:
"""
Get chrome setup to allow self signed certificates
"""
options = webdriver.ChromeOptions()
if headless == True:
options.headless = True
options.add_argument("window-size=1920x1080")
options.add_argument('ignore-certificate-errors')
options.add_argument("--start-maximized")
options.add_experimental_option("excludeSwitches", ["enable-logging"]) # Disable logging
return options
def __get_chrome_driver(drivers_path, headless) -> webdriver.Chrome:
"""
Return an instance of the chromedriver
"""
driver_path = os.path.join(drivers_path, 'chromedriver.exe')
service = ChromeService(driver_path)
return webdriver.Chrome(
service=service,
options=__get_chrome_options(headless)
)
Now I want to find a login element:
from loguru import logger
from selenium import webdriver
from selenium.webdriver.support.ui import WebDriverWait
from selenium.common.exceptions import TimeoutException
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By
from selenium.webdriver.remote.webelement import WebElement
def access_login_page(driver: webdriver.Chrome or webdriver.Firefox) -> None:
"""
Access the login page using the header menu
"""
ELEMENT_ID = 'header-sign-in'
try:
element: WebElement = WebDriverWait(driver, timeout=30).until(
EC.element_to_be_clickable((By.ID, ELEMENT_ID))
)
element.click()
except TimeoutException:
logger.error(f'Element "{ELEMENT_ID}" could not be found')
So this small piece of code works in chrome, chrome headless and firefox, but not in firefox headless.
Before I was having an element not interactable exception, therefore I changed it to element_to_be_clickable, but not it justs is stucked there and ends up with the TimeoutException.
I am not able to debug it because in the non headless mode it works, how can I try to fix this? What can be different in the configuration of firefox when the headless proeperty is used?
If it helps to get an idea, this is how the DOM looks like:
After minimizing the code to write this question I found the issue. The page has a responsive mode where the button I am using gets hidden at a certian screen size.
It seems taht in headless mode firefox takes a different resolution for driver.maximize_window() than running it in my full hd monitor not headless. Thereofre my monitor would return:
{'width': 1920, 'height': 1080}
while in headless mode:
{'width': 1366, 'height': 768}
Therefore I changed the following in the driver creation function:
if headless:
driver.set_window_size(1920, 1080)
else:
driver.maximize_window()
On the other hand I had to add this option driver.maximize_window() because the options options.add_argument("window-size=1920x1080") where not working out of the box for my firefox 96.0.3 (64-bit).
Okay, so I'm trying to keep the browser open once the script is finished executing. I want to be able to close it manually so the browser doens't close before the user is finished. I'll leave my code below and hopefully someone can help me to see where I'm going wrong. I'm using Chrome as browser. Version 90.0.4430.85
from selenium import webdriver
from selenium.webdriver.common.action_chains import ActionChains
# Launch the browser with 4 tabs.
def launchBrowser():
driver = webdriver.Chrome()
options = webdriver.ChromeOptions()
options.add_argument('start-maximized')
# Disables infobar: 'Chrome is being controlled by automation blah blah.' Check: https://github.com/GoogleChrome/chrome-launcher/blob/master/docs/chrome-flags-for-tools.md#--enable-automation if anything goes wrong.
options.add_experimental_option("excludeSwitches", ["enable-automation"])
# Ignores certificate and ssl errors.
options.add_argument('--ignore-certificate-errors')
options.add_argument('--ignore-ssl-errors')
# Doesn't work!
options.add_experimental_option("detach", True)
# Reject chrome notifications.
prefs = {'profile.default_content_setting_values.notifications': 2}
options.add_experimental_option('prefs', prefs)
# This line works for both the maximization of the window and the notifications preference.
driver = webdriver.Chrome(options=options, executable_path=r'C:\Users\Bernardo\Desktop\Python Projects\Automations\chromedriver.exe')
# Main browser, first tab - River.
driver.get('https://lapaginamillonaria.com/')
cookies_button = driver.find_element_by_class_name('fc-button.fc-cta-manage-options.fc-secondary-button')
ActionChains(driver).move_to_element(cookies_button).click(cookies_button).perform()
interes_legitimo = driver.find_element_by_class_name('fc-preference-legitimate-interest.purpose')
if interes_legitimo.get_attribute('checked') == 'true':
ActionChains(driver).move_to_element(interes_legitimo).click(interes_legitimo).perform()
enviar_button = driver.find_element_by_class_name('fc-button.fc-save-continue.fc-primary-button')
ActionChains(driver).move_to_element(enviar_button).click(enviar_button).perform()
else:
print("Couldn't proceed with our task, master Rari.")
# Second tab - La NaciĆ³n.
driver.execute_script("window.open('about:blank', 'tab2');")
driver.switch_to.window("tab2")
driver.get('https://www.lanacion.com.ar/')
# Third tab - BBC.
driver.execute_script("window.open('about:blank', 'tab3')")
driver.switch_to.window("tab3")
driver.get('https://www.bbc.com/')
cookies_button = driver.find_element_by_class_name('fc-button.fc-cta-manage-options.fc-secondary-button')
ActionChains(driver).move_to_element(cookies_button).click(cookies_button).perform()
interes_legitimo = driver.find_element_by_class_name('fc-preference-legitimate-interest.purpose')
if interes_legitimo.get_attribute('checked') == 'true':
ActionChains(driver).move_to_element(interes_legitimo).click(interes_legitimo).perform()
enviar_button = driver.find_element_by_class_name('fc-button.fc-save-continue.fc-primary-button')
ActionChains(driver).move_to_element(enviar_button).click(enviar_button).perform()
accept_continue = driver.find_element_by_class_name('continue-button.banner-button')
ActionChains(driver).move_to_element(accept_continue).click(accept_continue).perform()
else:
print("Couldn't proceed with our task.")
take_me_to_news = driver.find_element_by_class_name('orb-nav-newsdotcom')
ActionChains(driver).move_to_element(take_me_to_news).click(take_me_to_news).perform()
launching = launchBrowser()
I am having the worlds hardest time getting my Python Code to run headerless.. here's what I've done.
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
That's included at the top of my script, then I've included this.
def login(self, username, password):
self.destroyDriver()
try:
print(("Logging into => ", username))
chrome_options = webdriver.ChromeOptions()
# chrome_options.add_argument('--proxy-server=%s' % PROXY)
chrome_options.add_argument('--window-size=1420,1080')
chrome_options.add_argument('--headless')
self.driver = webdriver.Chrome()
self.driver.implicitly_wait(10)
self.driver.get("https://example.com")
time.sleep(5)
self.driver.find_element_by_class_name("sign-in").click()
time.sleep(6)
self.driver.find_element_by_name("avatarname").send_keys(username)
self.driver.find_element_by_name("password").send_keys(password)
self.driver.find_element_by_class_name("btn-primary").click()
time.sleep(4)
if "welcome/login" in self.driver.current_url:
self.destroyDriver()
return False
except:
self.destroyDriver()
return 17
return True
However, this doesn't work at all the Chrome tab still pops up. I am trying to run headerless because when the tab is minimized on my desktop the Javascript does not load properly, and causes the entire script to break forcing me to keep the tab constantly open.
you have to attach your option into your driver
self.driver = webdriver.Chrome(options=chrome_options)
So I was working on something that requires me to keep the browser open until unless it is closed by the user, however, the browser automatically closes after finishing its tasks, is there any way to prevent this?
def main():
driver = webdriver.Chrome()
driver.maximize_window()
driver.get("https://www.google.com/")
main()
If you want it to stay open, you have to use the 'detach' option
from selenium.webdriver.chrome.options import Options
def main():
chrome_options = Options()
chrome_options.add_experimental_option("detach", True)
driver = webdriver.Chrome(chrome_options=chrome_options)
driver.maximize_window()
driver.get("https://www.google.com/")
This should do it
Trying to run this code on my windows 10 machine https://github.com/KalleHallden/reddit_automations/blame/master/movie-tickets.py
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
from decouple import config
import time
# the way to locate the button or thing you want on a website in chrome is
# by pressing cmd + shift + c and then you can use your mouse to find the
# info on the element that you want and you can copy the full xpath.
options = webdriver.ChromeOptions()
# options.add_argument('--ignore-certificate-errors')
# options.add_argument('--incognito')
# options.add_argument('--headless')
driver = webdriver.Chrome("/Users/kalle/Downloads/chromedriver83", chrome_options=options)
driver.get(config('THEATRE_SITE'))
# for some odd reason you need to reload the site for it to load.
# possibly a bug of the theatre site
driver.get(config('THEATRE_SITE'))
time.sleep(3)
# select city
button = driver.find_element_by_xpath('/html/body/div[1]/div[3]/div/div/div[1]/div/div[2]/ul/li[1]/label/input')
button.click()
# save city
button = driver.find_element_by_xpath('/html/body/div[1]/div[3]/div/div/div[2]/span/button')
button.click()
time.sleep(2)
# proceed to tickets tab
button = driver.find_element_by_xpath('/html/body/div[1]/nav/div[2]/div[2]/div[1]/ul[1]/li[1]/a')
button.click()
time.sleep(2)
# select the movie you want (should be more specific than just selecting the first one but whateva)
button = driver.find_element_by_xpath('/html/body/div[1]/main/div/div[2]/div/div/div/div[2]/div/div[2]/div[2]/div[2]/ul/li[1]/ul/li/div/div[1]/div/span[2]/a')
button.click()
time.sleep(1)
# select the time you want to go
button = driver.find_element_by_xpath('/html/body/div[1]/main/div/div[1]/div/div/div/div[4]/section/div/div[2]/div[2]/ul/li/ul/li[1]/div/span/span[3]/span[2]/span')
button.click()
time.sleep(1)
# choose amount of people
button = driver.find_element_by_xpath('/html/body/div[1]/main/div/div[2]/div/div/div/div/section/div/div[2]/div/button')
button.click()
time.sleep(2)
# choose seats
button = driver.find_element_by_xpath('/html/body/div[1]/main/div/div[1]/div/div/div/div[2]/section/div[3]/div[2]/button')
button.click()
time.sleep(2)
# pay
button = driver.find_element_by_xpath('/html/body/div[1]/main/div/div[1]/div/div/div/div[2]/section/div[4]/div/div[2]/button/span')
button.click()
I have all the correct programs installed:
running python 3.8
have chrome webdriver installed
running version 84 stable chrome web browser
When I run the program it opens chrome however I get a blank web page with nothing on there but some text which says "data:." that is all nothing else.
This is the error I get in VS code:
:\Users\user>python c:/chromedriver_win32/movie-tickets1.py
c:/chromedriver_win32/movie-tickets1.py:15: DeprecationWarning: use options instead of chrome_options
driver = webdriver.Chrome(executable_path=r'C:\chromedriver_win32\chromedriver.exe', chrome_options=options)
DevTools listening on ws://127.0.0.1:29442/devtools/browser/872d4312-b51d-4a38-bc1b-3b80495950
Traceback (most recent call last):
File "c:/chromedriver_win32/movie-tickets1.py", line 17, in <module>
driver.get(config("https://www.google.co.uk"))
File "C:\Users\user\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.8_qbz5n2kfra8p0\LocalCache\local-packages\Python38\site-packages\decouple.py", line 199, in __call__
return self.config(*args, **kwargs)
File "C:\Users\user\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.8_qbz5n2kfra8p0\LocalCache\local-packages\Python38\site-packages\decouple.py", line 83, in __call__
return self.get(*args, **kwargs)
File "C:\Users\user\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.8_qbz5n2kfra8p0\LocalCache\local-packages\Python38\site-packages\decouple.py", line 68, in get
raise UndefinedValueError('{} not found. Declare it as envvar or define a default value.'.format(option))
decouple.UndefinedValueError: https://www.google.co.uk not found. Declare it as envvar or define a default value.
Any help would be much appreciated, I am unsure why decouple is not working.
This error message...
DeprecationWarning: use options instead of chrome_options
...implies that in your program you have used chrome_options to initiate a Selenium driven ChromeDriver initiated google-chrome Browsing Context.
chrome_options is deprecated now and you have to use options instead as well as pass the absolute path of the ChromeDriver along with the extension.
Solution
As you are triggering your tests on a windows-10 system, effectively you line of code will be:
options = webdriver.ChromeOptions()
options.add_argument('--headless')
driver = webdriver.Chrome(executable_path=r'C:\chromedriver_win32\chromedriver.exe', options=options)
It's ok!
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
chrome_options = Options()
chrome_options.add_argument('--headless')
browser = webdriver.Chrome(options=chrome_options)
no, the error will remain if you cover it like this
browser = webdriver.Chrome(options=chrome_options)
it will be right
browser = webdriver.Chrome(options=options)
***Below code sample is from 2022 and uses Web Driver Manager (https://pypi.org/project/webdriver-manager/)
#Imports for Web Driver, Service, Web Driver Manager
from selenium import webdriver
from selenium.webdriver.chrome.service import Service as ChromeService
from webdriver_manager.chrome import ChromeDriverManager
#options reference to Chrome Options
options = webdriver.ChromeOptions()
options.add_argument("--start-maximized")
#Pass options to the WebDriver with ChromeDriverManager
driver = webdriver.Chrome(service=ChromeService(ChromeDriverManager().install()), options=options)