Check if there is any selenium already open with firefox in python - python

I've been trying for some time to get this function to work, but I've tried several ways and I still can't. can anybody help me?
My goal is to prevent multiple browsers from being opened, that is, to check if there is already an instance of selenium firefox already open and return it so that the already open window can be used.
I tried with webdriver.remote, but no success.
from selenium import webdriver
from selenium.webdriver.firefox.service import Service
from webdriver_manager.firefox import GeckoDriverManager
def getDriver():
if isAlreadyRunning() == False:
firefox_service = Service(GeckoDriverManager().install())
driver = webdriver.Firefox(service=firefox_service)
return driver
else:
# Get the driver from the previous instance
return driver
def isAlreadyRunning():
try:
# Checks if a previous instance already exists to avoid opening a new browser
return True
except:
print('Driver is not running')
return False
driver = getDriver()
driver.get('https://stackoverflow.com')
The last attempts were activating the option marionette.debugging.clicktostart in about:config, opening cmd and starting firefox with the options:
cd 'C:\Program Files\Mozilla Firefox\'
.\firefox.exe -marionette -start-debugger-server 2828
and the code snippet below:
firefox_service = Service(GeckoDriverManager().install(), service_args=['--marionette-port', '2828', '--connect-existing'])
driver = webdriver.Firefox(service=firefox_service)
But after several seconds, selenium.common.exceptions.TimeoutException error is thrown
I'm using:
Python 3.10.4
Selenium 4.5.0

The below snippet isn't exactly your solution, but it would show a prompt if more than one instance of firefox is commanded by the program to run. The prompt would look like this although this won't focus on the opened window, the code would start running on that already open instance of Firefox, avoiding the clutter of multiple instances.
options = Options()
options.add_argument("-profile")
options.add_argument(os.path.expanduser("~")+"/AppData/Local/Mozilla/Firefox/Profiles")
firefox_capabilities = DesiredCapabilities.FIREFOX
firefox_capabilities['marionette'] = True
browser = webdriver.Firefox(capabilities=firefox_capabilities, options=options , executable_path= 'Whatsapp-Automation\geckodriver\geckodriver.exe')
This code snippet would create a unique profile of Firefox, so all your logins if done here would also be saved here.
Note: These are the required imports
from selenium import webdriver
import os
from selenium.webdriver.firefox.options import Options
from selenium.webdriver.common.desired_capabilities import DesiredCapabilities

use psutil to check if any geckodriver is opened
import psutil
for proc in psutil.process_iter():
if "geckodriver" in proc.name():
print("- found..")
and use that to check firefox
for proc in psutil.process_iter():
if "firefox" in proc.name():
print(proc.cmdline())
check cmdline if contain current args

Related

Opening a new unfocused tab in Chrome or Firefox with Python on Windows OS

My OS → Microsoft Windows 11
GOOGLE CHROME:
I have Google website open and I want to open the Stack Overflow website in a new tab but the screen keeps showing the Google website, like this:
My first attempt was trying it with the webbrowser module and its autoraise argument:
sof = 'https://stackoverflow.com'
webbrowser.open(sof, new=0, autoraise=False)
webbrowser.open(sof, new=2, autoraise=False)
webbrowser.open_new_tab(sof)
None of the above options caused the tab in Chrome to open in the background keeping focus on the tab that was already open.
So I went for another try using subprocess and its getoutput function:
r = subprocess.getoutput(f"google-chrome-stable https://stackoverflow.com")
r
That option didn't even open a new tab in my browser.
MOZILLA FIREFOX:
My attempt was trying it with the webbrowser module and its autoraise argument (As my default browser is different I need to set the browser):
sof = 'https://stackoverflow.com'
webbrowser.register('firefox',
None,
webbrowser.BackgroundBrowser("C://Program Files//Mozilla Firefox//firefox.exe"))
webbrowser.get('firefox').open(sof, new=0, autoraise=False)
In neither of the two I managed to make this functionality work.
How should I proceed?
Chrome:
I don't think it is feasible (at least not w/ chrome).
See this StackExchange answer for details. Especially the mentioned bug that most likely will never get fixed.
Firefox:
Same here, did some research and the only solution to get it to work is changing the config option
'browser.tabs.loadDivertedInBackground' to 'true'
launch background tab like this (or from py with os or subprocess module):
"C:\Program Files\Mozilla Firefox\firefox.exe" -new-tab "https://stackoverflow.com/"
See https://stackoverflow.com/a/2276679/2606766. But again I don't think this solves your problem, does it?
maybe you can try to stimulate the keyboard using pynput library,
then stimulating crtl + Tab to change to the new open website?
*edit: to open the previous tab, press crtl + shift + tab
import webbrowser, time
from pynput.keyboard import Key,Controller
keyboard = Controller()
webbrowser.open("https://www.youtube.com/")
time.sleep(3)
keyboard.press(Key.ctrl)
keyboard.press(Key.shift)
keyboard.press(Key.tab)
keyboard.release(Key.ctrl)
keyboard.release(Key.shift)
keyboard.release(Key.tab)
Are you familiar with CDP and Selenium?
Option A:
CDP Via Selenium Controlled browser:
from selenium import webdriver
driver = webdriver.Chrome('/path/bin/chromedriver')
driver.get("https://example.com/")
driver.execute_cdp_cmd(cmd="Target.createTarget",cmd_args={"url": 'https://stackoverflow.com/', "background": True})
"background": True is key
EDIT:
On linux the browser doesn't close, at least for me.
If it dies when the code dies, try the following:
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
CHROME_DRIVER_PATH = '/bin/chromedriver'
chrome_options = Options()
chrome_options.add_experimental_option("excludeSwitches", ["enable-automation"])
chrome_options.add_experimental_option("detach", True)
driver = webdriver.Chrome(CHROME_DRIVER_PATH, chrome_options=chrome_options)
driver.get("https://example.com/")
driver.execute_cdp_cmd(cmd="Target.createTarget",cmd_args={"url": 'https://stackoverflow.com/', "background": True})
Option B:
Manually run chrome with a debug port (via cmd, subprocess.popen or anything else)
chrome.exe --remote-debugging-port=4455
and then either use a python CDP Client such as trio
or tell selenium to use your existing browser:
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
chrome_options = Options()
chrome_options.add_experimental_option("debuggerAddress", "127.0.0.1:4455")
# Change chrome driver path accordingly
CHROME_DRIVER_PATH= r"C:\chromedriver.exe"
driver = webdriver.Chrome(CHROME_DRIVER_PATH, chrome_options=chrome_options)
driver.get("https://example.com/")
driver.execute_cdp_cmd(cmd="Target.createTarget",cmd_args={"url": 'https://stackoverflow.com/', "background": True})
Simpliest is to switch to -1 window_handles with chromedriver
from selenium import webdriver
driver = webdriver.Chrome('chrome/driver/path')
driver.switch_to.window(driver.window_handles[-1])

how to make selenium run 'chrome.exe --remote-debugging-port=9222 --user-data-dir='C:\\selenium\\ChromeProfile'

I am writing code to make selenium take over an instance of chrome that has all my bookmarks and stuff. So I created a chrome profile and I have the command
chrome.exe --remote-debugging-port=9222 --user-data-dir='C:\\selenium\\ChromeProfile'
this works when you run it in the python terminal, but I can't just put it into the code.
I have tried using
import os
os.system("chrome.exe --remote-debugging-port=9222 --user-data-dir='C:\\selenium\\ChromeProfile'")
but that returns with
Failed To Create Data Directory: Google Chrome cannot read and write to its data directory: C\selenium\ChromeProfile
Does someone know what I am doing wrong or a command that will run the chrome command to open this specific profile?
My total code so far looks like this
import subprocess
import os
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.chrome.options import Options
os.system("chrome.exe --remote-debugging-port=9222 --user-data-dir='C:\\selenium\\ChromeProfile'")
chrome_options = Options()
chrome_options.add_experimental_option("debuggerAddress", "127.0.0.1:9222")
chrome_driver = "C:\\selenium\\chromedriver.exe"
driver = webdriver.Chrome(chrome_driver, chrome_options=chrome_options)
#Print website title to make sure its connected properly
driver.get('https://google.com')
print(driver.title)
search_bar = driver.find_element_by_name('q')
search_bar.send_keys('test')
Nevermind people, I figured it out. I am posting this here for anyone else in the future who may run into the same issue I did where you want python to open the browser in debug mode on the port.
Here is the code
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
chrome_options = Options()
chrome_options.add_argument("--remote-debugging-port=9222")
chrome_options.add_argument('user-data-dir=C:\\selenium\\ChromeProfile')
chrome_driver = "C:\\selenium\\chromedriver.exe"
driver = webdriver.Chrome(chrome_driver, chrome_options=chrome_options)
#Print website title to make sure its connected properly
driver.get('https://google.com')
print(driver.title)
search_bar = driver.find_element_by_name('q')
search_bar.send_keys('test')
I had to add two lines of
chrome_options.add_argument()
for some reason it didn't like when I put them in the same parenthesis.
I hope I help someone in the future.

Selenium Chromedriver.exe continues to show terminal black screen even after executing as headless

I am attempting to automate a website process with Selenium in Python. I am using ChromeDriverManager to install the correct version of Chrome driver upon the execution of my program. I have a GUI program that calls my Selenium program via command-line arguments. My goal is to execute this program without any extra pop-ups from chromedriver.exe. I have the following code:
op = webdriver.ChromeOptions()
op.ignore_zoom_level = True
op.add_argument('headless')
op.add_argument('disable-gpu')
op.add_argument('disable-infobars')
op.add_experimental_option('excludeSwitches', ['enable-logging'])
driver = webdriver.Chrome(ChromeDriverManager().install(), options=op, service_args=['CREATE_NO_WINDOW'])
When I run this code via script I see no windows from chromedriver.exe, however, when I export to EXE package via pyinstaller a chromedriver.exe window pops up:
Terminal IMG
How do I disable this terminal window from chromedriver.exe from popping up?
To clarify this is not an issue with the main program appearing in the terminal. It is an issue when the main program executes chromedriver.exe.
Upon additional research, I found a solution to the issue. I added a service creation flag CREATE_NO_WINDOW and this solved the issue. Code change reference below:
from selenium.webdriver.chrome.service import Service as ChromeService
from subprocess import CREATE_NO_WINDOW
op = webdriver.ChromeOptions()
op.ignore_zoom_level = True
op.add_argument('--headless')
op.add_argument('--disable-gpu')
op.add_argument('--disable-infobars')
op.add_experimental_option('excludeSwitches', ['enable-logging'])
serv = ChromeService(ChromeDriverManager().install())
serv.creationflags = CREATE_NO_WINDOW
driver = webdriver.Chrome(service=serv, options=op)
You are passing arguments to ChromeOptions wrongly. You are missing -- in all the arguments.
Please try this:
op = webdriver.ChromeOptions()
op.ignore_zoom_level = True
op.add_argument('--headless')
op.add_argument('--disable-gpu')
op.add_argument('--disable-infobars')
op.add_experimental_option('excludeSwitches', ['enable-logging'])
driver = webdriver.Chrome(ChromeDriverManager().install(), options=op, service_args=['CREATE_NO_WINDOW'])
For me CREATE_NO_WINDOW gave nothing so I made a taskkill with filters to stop only the chromedriver.exe window
# /fi "memusage lt 12000" allows to filter processes under 12 Mb
subprocess.call('taskkill /f /IM chromedriver.exe /fi "memusage lt 12000"')
import os,logging
os.environ["WDM_LOG_LEVEL"] = str(logging.WARNING)

How to open a url using an adress of an application

How to open a URL without webbrowser using Python, but with an address of the application with which I want to open it.
There are three ways to do this
Case 1: You just need to open a page. and that is it,
import webbrowser
webbrowser.open("https://yoursite.com")
The above will open https://yoursite.com on your default browser
Case 2: You need to open, as well as do a task eg refresh
from selenium import webdriver
import time
driver = webdriver.Edge("path to your edge driver")
driver.get("https://yoursite.com")
# The command below will refresh your webbrowser after 3 seconds of opening it
time.sleep(3)
driver.refresh()
If you want to use chrome... use driver = webdriver.Chrome("path to your chrome driver")
Case 3:You have already opened your webbrowser (via selenium) and you are in another program and you want to see it without opening it manually
from selenium import webdriver
import time
driver = webdriver.Edge("path to your edge driver")
driver.get("https://yoursite.com")
time.sleep(10)
# this command stores your webbrowser window in a variable
main_page = driver.current_window_handle
# this command moves the webbrowser to the front
driver.switch_to.window(main_page)
Also you have to install a driver for your browser if you are using the selenium thing...
For edge go to https://developer.microsoft.com/en-us/microsoft-edge/tools/webdriver/#:~:text=Microsoft%20Edge%20WebDriver%20for%20Microsoft%20Edge%20will%20work,find%20your%20correct%20build%20number%3A%20Launch%20Microsoft%20Edge. and choose your edge version...
And for chrome go to https://chromedriver.chromium.org/downloads
You will also have to do pip install selenium in the terminal...
Hope this helps ;)
Try selenium, although you'll have to first download Chromedriver:
from selenium import webdriver from selenium.webdriver.common.keys import Keys
driver = webdriver.Firefox() driver.get("http://stackoverflow.com/")
body = driver.find_element_by_tag_name("body") body.send_keys(Keys.CONTROL + 't')
driver.close()

How to save Firefox webdriver session in python

To save chromedriver session, I used this snippet of code:
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
options = Options()
options.add_argument('user-data-dir= path to where to save session')
driver = webdriver.Chrome(executable_path='path to chromedriver.exe', chrome_options=options)
I tried to do the same thing with Firefox but it doesn't seem to work:
from selenium import webdriver
from selenium.webdriver.firefox.options import Options
options = Options()
options.add_argument('user-data-dir= path to where to save session')
driver = webdriver.Firefox(executable_path='path to geckodriver.exe', firefox_options=options)
Is this the right way to go or did I miss something?
Below is the manual process to create a new profile and start firefox using existing profile:
To create a new profile, execute command: firefox.exe -CreateProfile JoelUser
To create a new profile in another directory, execute command: firefox.exe -CreateProfile "JoelUser c:\internet\joelusers-moz-profile"
To start firefox using new profile, execute command: firefox.exe -P "Joel User"
Now, to achieve the same programmatically, I figured out that step no. 1 or 2 can be executed using subprocess and step no. 3 can be achieved by following https://stackoverflow.com/a/54065166/6278432
References:
firefox bug - unable to create new session using custom profile: https://github.com/mozilla/geckodriver/issues/1058
https://bugzilla.mozilla.org/show_bug.cgi?id=1421766
Firefox command line params - https://developer.mozilla.org/en-US/docs/Mozilla/Command_Line_Options#user_profile
subprocess api doc - https://docs.python.org/3/library/subprocess.html

Categories

Resources