如何防止 Selenium 3.0 (Geckodriver) 创建临时 Firefox 配置文件?

alp*_*ha1 8 java selenium selenium-webdriver geckodriver

我正在使用Geckodriver运行最新版本的Selenium WebDriver。我想阻止Selenium在启动WebDriver的新实例时在临时文件目录中创建临时 Firefox 配置文件。相反,我想直接使用原始的 Firefox 配置文件。这有双重好处。首先,它节省了时间(将配置文件复制到临时目录需要花费大量时间)。其次,它确保在会话期间创建的 cookie 保存到原始配置文件中。之前硒开始依赖Geckodriver我能解决这个问题,通过编辑类中,如下图所示:FirefoxProfile.classSeleniumHQ

public File layoutOnDisk() {

 File profileDir;

 if (this.disableTempProfileCreation) {
  profileDir = this.model;
  return profileDir;

  } else {

   try {
    profileDir = TemporaryFilesystem.getDefaultTmpFS().createTempDir("ABC", "XYZ");
    File userPrefs = new File(profileDir, "user.js");
    this.copyModel(this.model, profileDir);
    this.installExtensions(profileDir);
    this.deleteLockFiles(profileDir);
    this.deleteExtensionsCacheIfItExists(profileDir);
    this.updateUserPrefs(userPrefs);
    return profileDir;
    } catch (IOException var3) {
   throw new UnableToCreateProfileException(var3);
  }
 }
}
Run Code Online (Sandbox Code Playgroud)

当参数disableTempProfileCreation设置为 true时,这将阻止 Selenium 创建临时 Firefox 配置文件。

但是,现在 Selenium 由Geckodriver控制,此解决方案不再有效,因为 Firefox Profile 的创建(和启动)由Geckodriver.exe(用Rust语言编写)控制。如何使用Geckodriver实现相同的目标?我不介意编辑源代码。我正在使用 Java。

谢谢

重要更新:

我要感谢大家花时间回答这个问题。然而,正如一些评论中所述,前 3 个答案根本没有解决这个问题——有两个原因。首先,使用现有的 Firefox 配置文件不会阻止Geckodriver将原始配置文件复制到临时目录(如 OP 所示,并由以下一位或多位评论员明确说明)。其次,即使这样做了,它也与 Selenium 3.0 不兼容。

我真的不知道为什么 4 个答案中有 3 个会以完全相同的错误重复完全相同的答案。他们是否阅读了问题?即使试图解决手头问题的唯一答案是@Life 的答案很复杂,但它并不完整。谢谢。

Lif*_*lex 8

更新帖子 2021 年 5 月 30 日

\n
\n

这是我在 Stack Overflow 上尝试过回答的最难的问题。因为它涉及用多种语言(Java、Rust 和 C++)编写的多个代码库的交互。这种复杂性使得这个问题可能无法解决。

\n

我对这个可能无法解决的问题的最后一次尝试:

\n

在您问题的代码中,您正在修改文件user.js该文件仍由Selenium使用。

\n
public FirefoxProfile() {\n    this(null);\n  }\n\n  /**\n   * Constructs a firefox profile from an existing profile directory.\n   * <p>\n   * Users who need this functionality should consider using a named profile.\n   *\n   * @param profileDir The profile directory to use as a model.\n   */\n  public FirefoxProfile(File profileDir) {\n    this(null, profileDir);\n  }\n\n  @Beta\n  protected FirefoxProfile(Reader defaultsReader, File profileDir) {\n    if (defaultsReader == null) {\n      defaultsReader = onlyOverrideThisIfYouKnowWhatYouAreDoing();\n    }\n\n    additionalPrefs = new Preferences(defaultsReader);\n\n    model = profileDir;\n    verifyModel(model);\n\n    File prefsInModel = new File(model, "user.js");\n    if (prefsInModel.exists()) {\n      StringReader reader = new StringReader("{\\"frozen\\": {}, \\"mutable\\": {}}");\n      Preferences existingPrefs = new Preferences(reader, prefsInModel);\n      acceptUntrustedCerts = getBooleanPreference(existingPrefs, ACCEPT_UNTRUSTED_CERTS_PREF, true);\n      untrustedCertIssuer = getBooleanPreference(existingPrefs, ASSUME_UNTRUSTED_ISSUER_PREF, true);\n      existingPrefs.addTo(additionalPrefs);\n    } else {\n      acceptUntrustedCerts = true;\n      untrustedCertIssuer = true;\n    }\n\n    // This is not entirely correct but this is not stored in the profile\n    // so for now will always be set to false.\n    loadNoFocusLib = false;\n\n    try {\n      defaultsReader.close();\n    } catch (IOException e) {\n      throw new WebDriverException(e);\n    }\n  }\n
Run Code Online (Sandbox Code Playgroud)\n

所以理论上你应该能够修改geckodriver源代码中的capability.rs。该文件包含temp_dir

\n

正如我在理论上所说的那样,因为当我查看 Firefox 源代码时,它的temp_dir分布在整个代码库中。

\n

原帖于 2021 年 5 月 26 日

\n
\n

我不确定您是否可以阻止 Selenium 创建临时 Firefox 配置文件。

\n

来自壁虎文档

\n

“配置文件是在系统临时文件夹中创建的。当提供配置文件时,这也是提取编码配置文件的位置。默认情况下,geckodriver 将在此位置创建一个新的配置文件。”

\n

我目前看到的唯一解决方案需要修改 Geckodriver 源文件以防止创建临时文件夹/配置文件。

\n

我目前正在查看源代码。这些文件可能是正确的,但我需要更多地查看源代码:

\n\n

以下是一些其他需要梳理的文件:

\n

https://searchfox.org/mozilla-central/search?q=tempfile&path=

\n
\n

这看起来很有希望:

\n

https://searchfox.org/mozilla-central/source/testing/geckodriver/doc/Profiles.md

\n

“geckodriver 使用 [配置文件] 来检测 Firefox\xe2\x80\x99 的行为。用户通常会依赖 geckodriver 来生成临时的、一次性的配置文件。这些配置文件将在 WebDriver 会话过期时被删除。

\n

如果用户需要使用自定义的、准备好的配置文件,\neckodriver 将对配置文件进行修改,以确保\n正确的行为。请参阅下面的 [自动化首选项],了解\n在这种情况下用户定义的首选项的优先级。

\n

可以通过两种不同的方式提供自定义配置文件:

\n

1. 通过附加--profile /some/location到 [ capability],\n这将指示 geckodriver就地args使用配置文件;

\n

我在尝试执行此操作时发现了这个问题:How do I use an existing profile in-place with Selenium Webdriver?

\n

另外,Github 上的 selenium 中提出了一个关于临时目录的问题。https://github.com/SeleniumHQ/selenium/issues/8645

\n
\n

查看geckodriver v0.29.1的源代码,我发现了一个加载配置文件的文件。

\n

来源:capability.rs

\n
public FirefoxProfile() {\n    this(null);\n  }\n\n  /**\n   * Constructs a firefox profile from an existing profile directory.\n   * <p>\n   * Users who need this functionality should consider using a named profile.\n   *\n   * @param profileDir The profile directory to use as a model.\n   */\n  public FirefoxProfile(File profileDir) {\n    this(null, profileDir);\n  }\n\n  @Beta\n  protected FirefoxProfile(Reader defaultsReader, File profileDir) {\n    if (defaultsReader == null) {\n      defaultsReader = onlyOverrideThisIfYouKnowWhatYouAreDoing();\n    }\n\n    additionalPrefs = new Preferences(defaultsReader);\n\n    model = profileDir;\n    verifyModel(model);\n\n    File prefsInModel = new File(model, "user.js");\n    if (prefsInModel.exists()) {\n      StringReader reader = new StringReader("{\\"frozen\\": {}, \\"mutable\\": {}}");\n      Preferences existingPrefs = new Preferences(reader, prefsInModel);\n      acceptUntrustedCerts = getBooleanPreference(existingPrefs, ACCEPT_UNTRUSTED_CERTS_PREF, true);\n      untrustedCertIssuer = getBooleanPreference(existingPrefs, ASSUME_UNTRUSTED_ISSUER_PREF, true);\n      existingPrefs.addTo(additionalPrefs);\n    } else {\n      acceptUntrustedCerts = true;\n      untrustedCertIssuer = true;\n    }\n\n    // This is not entirely correct but this is not stored in the profile\n    // so for now will always be set to false.\n    loadNoFocusLib = false;\n\n    try {\n      defaultsReader.close();\n    } catch (IOException e) {\n      throw new WebDriverException(e);\n    }\n  }\n
Run Code Online (Sandbox Code Playgroud)\n

来源:marionette.rs

\n
   fn load_profile(options: &Capabilities) -> WebDriverResult<Option<Profile>> {\n        if let Some(profile_json) = options.get("profile") {\n            let profile_base64 = profile_json.as_str().ok_or_else(|| {\n                WebDriverError::new(ErrorStatus::InvalidArgument, "Profile is not a string")\n            })?;\n            let profile_zip = &*base64::decode(profile_base64)?;\n\n            // Create an emtpy profile directory\n            let profile = Profile::new()?;\n            unzip_buffer(\n                profile_zip,\n                profile\n                    .temp_dir\n                    .as_ref()\n                    .expect("Profile doesn\'t have a path")\n                    .path(),\n            )?;\n\n            Ok(Some(profile))\n        } else {\n            Ok(None)\n        }\n    }\n\n
Run Code Online (Sandbox Code Playgroud)\n

查看 gecko 源代码后,看起来mozprofile::profile::Profile来自 FireFox 而不是 geckodriver

\n
\n

当您迁移到 Selenium 4 时,您似乎可能会遇到配置文件问题。

\n

参考: https: //github.com/SeleniumHQ/selenium/issues/9417

\n

对于 Selenium 4,我们已弃用配置文件,因为我们可以采用其他机制来加快启动速度。\n请使用 Options 类来设置您需要的首选项,如果您需要使用插件,请使用驱动程序。 install_addon("path/to/addon")\n您可以通过 pip install selenium --pre 安装处于测试版的 selenium 4

\n
\n

我在你的代码中注意到你正在写入user.js,这是 FireFox 的自定义文件。您是否考虑过在 Gecko 之外手动创建这些文件?

\n

您还看过mozprofile吗?

\n


Sra*_*lla 0

如果未设置任何选项,新驱动程序默认会创建一个新配置文件。webdriver.firefox.profile要使用现有配置文件,一种方法是在创建 Firefox 驱动程序之前设置系统属性。一个可以创建 Firefox 驱动程序的小代码片段(假设您有 geckodriver 和 Firefox 配置文件的位置):

System.setProperty("webdriver.gecko.driver","path_to_gecko_driver");
System.setProperty("webdriver.firefox.profile", "path_to_firefox_profile");
WebDriver driver = new FirefoxDriver();
Run Code Online (Sandbox Code Playgroud)

您甚至可以使用 env 设置这些系统属性。变量并跳过到处定义它们。

另一种方法是使用 FirefoxOptions 类,它允许您配置许多选项。首先,看一下org.openqa.selenium.firefox.FirefoxDriverorg.openqa.selenium.firefox.FirefoxOptions。一个小例子:

FirefoxOptions options = new FirefoxOptions();
options.setProfile(new FirefoxProfile(new File("path_to_your_profile")));
WebDriver driver = new FirefoxDriver(options);
Run Code Online (Sandbox Code Playgroud)

希望这有帮助。