如何让Selenium管控的Firefox实例在脚本终止后保持运行并可重连
实现Selenium复用Firefox实例的方案
核心思路
- 首次执行脚本时,通过Selenium启动带有Marionette调试端口的Firefox实例,并配置实例在脚本终止后保留运行
- 后续执行脚本时,先检测指定端口是否有运行的Firefox实例,若存在则直接连接,无需重新启动
- 全程基于Selenium官方API实现,无需使用
popen子进程
关键配置要点
- 指定Firefox二进制路径:由于系统默认未安装Firefox,需明确指向
~/.cache/firefox中的Firefox可执行文件(Windows下为.exe,Linux/macOS下为对应可执行文件) - 开启Marionette调试端口:添加
--marionette-port=2828参数(可自定义端口),允许Selenium后续连接实例 - 保留浏览器实例:设置
options.detach = True,避免脚本终止时Firefox被自动关闭 - 端口可用性检测:通过尝试建立socket连接,判断目标端口是否已有Firefox实例在监听
修改后的完整代码
from selenium.webdriver.firefox.options import Options from selenium import webdriver import socket from selenium.webdriver import Keys, ActionChains from selenium.webdriver.common.actions.action_builder import ActionBuilder from selenium.webdriver.common.by import By from selenium.webdriver.support.wait import WebDriverWait from selenium.webdriver.support import expected_conditions as EC class Browser: # 自定义配置项 MARIONETTE_PORT = 2828 # 替换为~/.cache/firefox中的Firefox可执行文件路径 FIREFOX_BINARY_PATH = "~/.cache/firefox/firefox" # Linux/macOS示例,Windows请改为类似"C:/Users/xxx/AppData/Local/Temp/firefox.exe" PROFILE_PATH = "C:/firefox/profile/" firefox_options = Options() firefox_options.add_argument("-profile") firefox_options.add_argument(PROFILE_PATH) # 开启Marionette端口 firefox_options.add_argument(f"--marionette-port={MARIONETTE_PORT}") # 设置脚本终止后保留浏览器实例 firefox_options.detach = True # 指定Firefox二进制文件路径 firefox_options.binary_location = FIREFOX_BINARY_PATH driver = None wait = None EC = EC By = By Keys = Keys ActionChains = ActionChains ActionBuilder = ActionBuilder @staticmethod def _is_port_in_use(port): """检测指定端口是否被占用""" with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s: return s.connect_ex(('localhost', port)) == 0 def __init__(self): try: if self._is_port_in_use(self.MARIONETTE_PORT): # 端口已占用,连接已运行的Firefox实例 self.driver = webdriver.Firefox.connect(f"http://localhost:{self.MARIONETTE_PORT}") else: # 端口未占用,启动新的Firefox实例 self.driver = webdriver.Firefox(options=self.firefox_options) self.wait = WebDriverWait(self.driver, timeout=15, poll_frequency=.2) except Exception as e: raise ValueError(f"浏览器连接或启动失败: {str(e)}")
代码说明
- 端口检测函数:
_is_port_in_use通过socket连接尝试,判断目标端口是否有Firefox实例在监听 - 实例分支逻辑:
- 若端口已被占用,调用
webdriver.Firefox.connect()连接已运行的实例 - 若端口未被占用,调用
webdriver.Firefox()启动新实例,同时通过配置确保实例在脚本退出后保留
- 若端口已被占用,调用
- 路径配置:需根据实际系统环境修改
FIREFOX_BINARY_PATH和PROFILE_PATH,确保路径正确
内容的提问来源于stack exchange,提问作者Neo Yion
相关产品推荐
相关产品推荐

