Selenium Remote WebDriver中Firefox Profile配置报错:无法JSON序列化
问题:Docker中配置Firefox Profile到Remote WebDriver失败,JSON序列化错误
尝试在Docker容器(selenium/standalone-firefox)中配置Firefox Profile运行Selenium测试,但无法整合capabilities、profile和options到Remote WebDriver。引入Profile相关设置时,持续出现如下报错:
^^^^^^^^^^^^^^^^^^^^^^^ File "C:\Program Files\WindowsApps\PythonSoftwareFoundation.Python.3.11_3.11.1008.0_x64__qbz5n2kfra8p0\Lib\json\__init__.py", line 231, in dumps return _default_encoder.encode(obj) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "C:\Program Files\WindowsApps\PythonSoftwareFoundation.Python.3.11_3.11.1008.0_x64__qbz5n2kfra8p0\Lib\json\encoder.py", line 200, in encode chunks = self.iterencode(o, _one_shot=True) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "C:\Program Files\WindowsApps\PythonSoftwareFoundation.Python.3.11_3.11.1008.0_x64__qbz5n2kfra8p0\Lib\json\encoder.py", line 258, in iterencode return _iterencode(o, 0) ^^^^^^^^^^^^^^^^^ File "C:\Program Files\WindowsApps\PythonSoftwareFoundation.Python.3.11_3.11.1008.0_x64__qbz5n2kfra8p0\Lib\json\encoder.py", line 180, in default raise TypeError(f'Object of type {o.__class__.__name__} ' TypeError: Object of type FirefoxProfile is not JSON serializable
以下是我的代码:
from selenium import webdriver from selenium.webdriver.common.by import By from selenium.webdriver.common.keys import Keys from time import sleep from selenium.webdriver.firefox.options import Options from selenium.webdriver.firefox.firefox_profile import FirefoxProfile capabilities = webdriver.DesiredCapabilities.FIREFOX.copy() capabilities['acceptInsecureCerts'] = True capabilities['marionette'] = True profile = webdriver.FirefoxProfile() profile.set_preference("accept_untrusted_certs", True) profile.set_preference("browser.download.panel.shown", False) profile.set_preference("browser.helperApps.neverAsk.openFile","text/csv,application/vnd.ms-excel") profile.set_preference("browser.helperApps.neverAsk.saveToDisk", "application/msword, application/csv, application/ris, text/csv, image/png, application/pdf, text/html, text/plain, application/zip, application/x-zip, application/x-zip-compressed, application/download, application/octet-stream") profile.set_preference("browser.download.manager.showWhenStarting", False) profile.set_preference("browser.download.manager.alertOnEXEOpen", False) profile.set_preference("browser.download.manager.focusWhenStarting", False) profile.set_preference("browser.download.folderList", 2) profile.set_preference("browser.download.useDownloadDir", True) profile.set_preference("browser.helperApps.alwaysAsk.force", False) profile.set_preference("browser.download.manager.alertOnEXEOpen", False) profile.set_preference("browser.download.manager.closeWhenDone", True) profile.set_preference("browser.download.manager.showAlertOnComplete", False) profile.set_preference("browser.download.manager.useWindow", False) profile.set_preference("services.sync.prefs.sync.browser.download.manager.showWhenStarting", False) profile.set_preference("pdfjs.disabled", True) profile.set_preference("javascript.enabled", False) profile.update_preferences() options=Options() options.set_preference('profile', profile) options.set_preference('network.proxy.type', 1) options.set_preference('network.proxy.socks', '127.0.0.1') options.set_preference('network.proxy.socks_port', 9050) options.set_preference('network.proxy.socks_remote_dns', False) driver = webdriver.Remote( command_executor="http://localhost:4444", desired_capabilities=capabilities, options=options ) driver.get("https://www.google.com") search_input_box = driver.find_element(By.NAME, "q") search_input_box.send_keys("selenium webdriver" + Keys.ENTER) sleep(60) driver.quit()
移除Profile或Options设置后可正常运行,但希望能自定义配置,请问问题出在哪里?
解决方案
问题根源
你直接将FirefoxProfile对象通过options.set_preference('profile', profile)传给了Options,但RemoteWebDriver需要把配置序列化成JSON格式传输给Docker中的Selenium节点,而FirefoxProfile对象本身无法被JSON序列化,这就是报错的直接原因。
解决方法(推荐:直接用Options管理所有偏好)
不需要单独创建FirefoxProfile对象,把所有Profile中的偏好设置直接通过Options.set_preference()来配置,这样所有参数都是可序列化的键值对,能正常传递给Remote节点。
修改后的代码如下:
from selenium import webdriver from selenium.webdriver.common.by import By from selenium.webdriver.common.keys import Keys from time import sleep from selenium.webdriver.firefox.options import Options capabilities = webdriver.DesiredCapabilities.FIREFOX.copy() capabilities['acceptInsecureCerts'] = True capabilities['marionette'] = True options=Options() # 原Profile中的所有偏好直接通过Options设置 options.set_preference("accept_untrusted_certs", True) options.set_preference("browser.download.panel.shown", False) options.set_preference("browser.helperApps.neverAsk.openFile","text/csv,application/vnd.ms-excel") options.set_preference("browser.helperApps.neverAsk.saveToDisk", "application/msword, application/csv, application/ris, text/csv, image/png, application/pdf, text/html, text/plain, application/zip, application/x-zip, application/x-zip-compressed, application/download, application/octet-stream") options.set_preference("browser.download.manager.showWhenStarting", False) options.set_preference("browser.download.manager.alertOnEXEOpen", False) options.set_preference("browser.download.manager.focusWhenStarting", False) options.set_preference("browser.download.folderList", 2) options.set_preference("browser.download.useDownloadDir", True) options.set_preference("browser.helperApps.alwaysAsk.force", False) options.set_preference("browser.download.manager.closeWhenDone", True) options.set_preference("browser.download.manager.showAlertOnComplete", False) options.set_preference("browser.download.manager.useWindow", False) options.set_preference("services.sync.prefs.sync.browser.download.manager.showWhenStarting", False) options.set_preference("pdfjs.disabled", True) options.set_preference("javascript.enabled", False) # 原代理设置保留 options.set_preference('network.proxy.type', 1) options.set_preference('network.proxy.socks', '127.0.0.1') options.set_preference('network.proxy.socks_port', 9050) options.set_preference('network.proxy.socks_remote_dns', False) driver = webdriver.Remote( command_executor="http://localhost:4444", desired_capabilities=capabilities, options=options ) driver.get("https://www.google.com") search_input_box = driver.find_element(By.NAME, "q") search_input_box.send_keys("selenium webdriver" + Keys.ENTER) sleep(60) driver.quit()
备选方法(适合复杂Profile场景)
如果必须使用FirefoxProfile对象,可以将其导出为ZIP文件,然后通过options.add_argument()指定--profile参数指向该ZIP路径。注意:Docker环境下需要确保该ZIP文件能被容器访问(比如通过挂载本地目录到容器)。
示例代码片段:
profile = webdriver.FirefoxProfile() # 配置Profile偏好... profile.update_preferences() # 导出为ZIP文件 profile_path = profile.path import shutil zip_path = "firefox_profile.zip" shutil.make_archive(zip_path.replace('.zip', ''), 'zip', profile_path) options=Options() # 指定Profile ZIP路径(Docker中需对应挂载路径) options.add_argument(f'--profile={zip_path}') # 其他代理设置...
内容的提问来源于stack exchange,提问作者Mr. E
相关产品推荐
相关产品推荐

