SeleniumでFirefoxのプロファイルを使う

Firefoxのプロファイル

Firefoxのユーザー毎のデータ(履歴、ブックマーク、パスワード等)は、プロファイルに保存されます。
SeleniumでFirefoxDriver(geckodriver)を動かす場合、デフォルトではプロファイルは一時ディレクトリに作成されます。
既存のプロファイルを利用して、ログイン情報を引き継ぎたい場合は、使用するプロファイルを指定する必要があります。

FirefoxDriverは、指定したプロファイルを一時ディレクトリにコピーした上で利用するため、Seleniumで実行した履歴は引き継がれません。
ログイン情報など、履歴を引き継ぎたい場合は、あらかじめ手動で操作しておく必要があります。

プロファイルの作成

Firefoxのプロファイルは、「プロファイルマネージャー」にて作成します。

1.Firefoxのアドレスバーに about:profiles と入力してプロファイルマネージャーを起動

about:profiles

2.「Create a New Profile(新しいプロファイルを作成)」ボタンを押す

Create a New Profile

3.プロファイル名と保存先を設定

4.プロファイルが作成される

Profile:User1
プロファイルの指定

使用するプロファイルはプロファイルマネージャーで指定できます。
別途、起動時のオプションで指定することも可能です。

firefox.exe -p User1

プロファイル名、または保存先ディレクトリを指定します。

firefox.exe -p プロファイル名
firefox.exe -profile プロファイルの保存先
This is the profile in use and it cannot be deleted.

上記のように、使用中のプロファイルが表示されます。

Firefox Driverでプロファイルを指定する

SeleniumでFirefoxを操作するには、FirefoxDriver(geckodriver)を利用します。
よって、FirefoxDriverに、使用するプロファイルを指定します。

from selenium import webdriver

profile = webdriver.FirefoxProfile(r'D:\tmp\Profile')
exe_path = r'D:\tmp\driver\geckodriver-v0.25.0-win64\geckodriver.exe'
log_path = r'D:\tmp\Firefox.log'

driver = webdriver.Firefox(firefox_profile=profile,
              executable_path=exe_path, log_path=log_path)
driver.get('about:profiles')
#driver.quit()'
package example;
import java.io.File;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.openqa.selenium.firefox.FirefoxOptions;
import org.openqa.selenium.firefox.FirefoxProfile;
 
public class fx_profile {
    public static void main( String[] args )
    {
        String exe_path = "D:/tmp/driver/geckodriver-v0.25.0-win64/geckodriver.exe";
        FirefoxOptions options = new FirefoxOptions();
        FirefoxProfile profile = new FirefoxProfile(new File("D:/tmp/Profile"));
            
        options.setProfile(profile);    //起動に長時間かかる
        System.setProperty("webdriver.gecko.driver", exe_path);
        long start = System.currentTimeMillis();
        WebDriver driver = new FirefoxDriver(options);
        long end = System.currentTimeMillis();
        System.out.println((end - start)/1000 + "s");
            
        driver.get("about:profiles");
        //driver.quit();
    }
}

134S
using System;
using OpenQA.Selenium;
using OpenQA.Selenium.Firefox;

namespace fx_profile
{
    class Program
    {
        static void Main(string[] args)
        {
            String exe_path = @"D:\tmp\driver\geckodriver-v0.25.0-win64";

            FirefoxOptions options = new FirefoxOptions();
            FirefoxProfile profile = new FirefoxProfile(@"D:\tmp\Profile");
            options.Profile = profile;
            
            IWebDriver driver = new FirefoxDriver(exe_path, options);
            driver.Navigate().GoToUrl("about:profiles");
            //driver.Quit();
        }
    }
}
Imports OpenQA.Selenium.Firefox
 
Module Module1
    Sub Main()
        Dim exe_path = "D:/tmp/driver/geckodriver-v0.25.0-win64"
        Dim options = New FirefoxOptions()
        Dim profile = New FirefoxProfile("D:/tmp/Profile")
        options.Profile = profile
            
        Dim driver = New FirefoxDriver(exe_path, options)
        driver.Navigate().GoToUrl("about:profiles")
        'driver.Quit()
    End Sub
End Module
require "selenium-webdriver"

exe_path = 'D:\tmp\driver\geckodriver-v0.25.0-win64\geckodriver.exe'
options = Selenium::WebDriver::Firefox::Options.new
options.profile = Selenium::WebDriver::Firefox::Profile.new("D:/tmp/Profile")

driver = Selenium::WebDriver.for :firefox, driver_path:exe_path, options:options
driver.get("about:profiles")
#driver.quit()
let webdriver = require('selenium-webdriver');
let firefox = require('selenium-webdriver/firefox');
let exe_path = "D:/tmp/driver/geckodriver-v0.25.0-win64/geckodriver.exe";

var options = new firefox.Options;
options.setProfile("D:/tmp/Profile");

(async () => {
    var driver = await new webdriver.Builder()
        .forBrowser('firefox')
        .setFirefoxOptions(options)
        .setFirefoxService(new firefox.ServiceBuilder(exe_path))
        .build();    
    await driver.get("about:profiles");
    //await driver.quit();
})();

結果画面

about:profiles

補足

SeleniumでFirefoxのプロファイルは、コピーして使用される

結果画面を見てみると、ブックマーク情報は引き継がれていますが、指定したプロファイル(User1)が使用中になっていません。

ログを見てみると

Running command: "C:\\Program Files\\Mozilla Firefox\\firefox.exe" "-marionette" "-foreground" "-no-remote" "-profile" "C:\\Users\\xxxxx\\AppData\\Local\\Temp\\rust_mozprofileOjCBx4"

起動コマンドで、プロファイルに一時領域を指定しています。どうやらFirefoxDriverでプロファイルを指定すると、一時領域にコピーして使用するようです。

一時領域ですので、Seleniumで操作した履歴情報は、次回起動時に引き継がれません。引き継ぎたい情報は、あらかじめ手動操作でプロファイルに記録しておく必要があります。

チャレンジ

FirefoxDriver(geckodriver)はオリジナルのプロファイルをコピーして、Firefoxを起動します。
では、Firefoxの起動オプションでオリジナルのプロファイルを指定した場合は、どうなるでしょうか?

次のコードを試してみます。

from selenium import webdriver
from selenium.webdriver.firefox.options import Options

options = Options()
options.add_argument('-profile')
options.add_argument('D:/tmp/Profile')

exe_path = r'D:\tmp\driver\geckodriver-v0.25.0-win64\geckodriver.exe'
log_path = r'D:\tmp\Firefox.log'

driver = webdriver.Firefox(options=options, executable_path=exe_path, log_path=log_path)
driver.get('about:profiles')
driver.quit()

selenium.common.exceptions.WebDriverException: Message: connection refused
package example.test;
import java.io.File;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.openqa.selenium.firefox.FirefoxOptions;
public class fx_profile {
    public static void main( String[] args )
    {
        String exe_path = "D:/tmp/driver/geckodriver-v0.25.0-win64/geckodriver.exe";
        FirefoxOptions options = new FirefoxOptions();
        options.addArguments("-profile");
        options.addArguments("D:/tmp/Profile");
            
        System.setProperty("webdriver.gecko.driver", exe_path);
        WebDriver driver = new FirefoxDriver(options);
            
        driver.get("about:profiles");
        driver.quit();
    }
}

Exception in thread "main" org.openqa.selenium.WebDriverException: connection refused
using System;
using OpenQA.Selenium;
using OpenQA.Selenium.Firefox;

namespace fx_profile
{
    class Program
    {
        static void Main(string[] args)
        {
            String exe_path = @"D:\tmp\driver\geckodriver-v0.25.0-win64";

            FirefoxOptions options = new FirefoxOptions();
            options.AddArgument("-profile");
            options.AddArgument("D:/tmp/Profile");
            
            IWebDriver driver = new FirefoxDriver(exe_path, options);
            driver.Navigate().GoToUrl("about:profiles");
            driver.Quit();
        }
    }
}

Exception thrown: 'OpenQA.Selenium.WebDriverException' in WebDriver.dll
An unhandled exception of type 'OpenQA.Selenium.WebDriverException' occurred in WebDriver.dll
Additional information: The HTTP request to the remote WebDriver server for URL http://localhost:52138/session timed out after 60 seconds.
Imports OpenQA.Selenium.Firefox
Module Module1
    Sub Main()
        Dim exe_path = "D:/tmp/driver/geckodriver-v0.25.0-win64"
        Dim options = New FirefoxOptions()
        options.AddArgument("-profile")
        options.AddArgument("D:/tmp/Profile")
            
        Dim driver = New FirefoxDriver(exe_path, options)
        driver.Navigate().GoToUrl("about:profiles")
        'driver.Quit()
    End Sub
End Module

Exception thrown: 'OpenQA.Selenium.WebDriverException' in WebDriver.dll
An unhandled exception of type 'OpenQA.Selenium.WebDriverException' occurred in WebDriver.dll
Additional information: The HTTP request to the remote WebDriver server for URL http://localhost:53168/session timed out after 60 seconds.
require "selenium-webdriver"

exe_path = 'D:\tmp\driver\geckodriver-v0.25.0-win64\geckodriver.exe'
options = Selenium::WebDriver::Firefox::Options.new
options.add_argument('-profile')
options.add_argument('D:/tmp/Profile')

driver = Selenium::WebDriver.for :firefox, driver_path:exe_path, options:options
driver.get("about:profiles")
driver.quit()

Uncaught exception: Net::ReadTimeout
let webdriver = require('selenium-webdriver');
let firefox = require('selenium-webdriver/firefox');
let exe_path = "D:/tmp/driver/geckodriver-v0.25.0-win64/geckodriver.exe";

var options = new firefox.Options;
options.addArguments("-profile");
options.addArguments("D:/tmp/Profile");

(async () => {
    var driver = await new webdriver.Builder()
        .forBrowser('firefox')
        .setFirefoxOptions(options)
        .setFirefoxService(new firefox.ServiceBuilder(exe_path))
        .build();    
    await driver.get("about:profiles");
    await driver.quit();
})();

UnhandledPromiseRejectionWarning: WebDriverError: connection refused

結果画面

Firefox Start

Firefoxは起動しますが、その後の操作ができません。タイムアウトでエラーになります。

アドレス欄に「about:profiles」を手入力します。

about:profiles

プロファイルの指定はできています。しかしSeleniumで操作できないのでは、意味がありません。
どうやらFirefoxDriver(geckodriver)でオリジナルのプロファイルを扱うのは難しいようです。

JavaからFirefoxDriverのプロファイルを使用すると遅い

JavaからFrifefoxDriver(geckodriver)のプロファイルを指定すると、起動に非常に時間がかかります。
(Windows10:selenium-java-3.141.59:geckodriver-v0.25.0-win64)

理由は分かりませんが、数分間かかる場合もあるので、「起動に失敗したのではないか?」と感じるほどです。

チャレンジ

Linux(仮想環境)で試してみます。
(Ubuntu20.04.1 LTS:selenium-java-3.141.59:geckodriver-v0.28.0-linux64)

package example
import java.io.File;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.openqa.selenium.firefox.FirefoxOptions;
import org.openqa.selenium.firefox.FirefoxProfile;
public class profile_fx1 {
    public static void main( String[] args )
    {
        String exe_path = "/home/sj/selenium/driver/geckodriver";
        FirefoxOptions options = new FirefoxOptions();
        FirefoxProfile profile = new FirefoxProfile(new File("/home/sj/selenium/tmp/Profile"));
            
        options.setProfile(profile);
        System.setProperty("webdriver.gecko.driver", exe_path);
        long start = System.currentTimeMillis();
        WebDriver driver = new FirefoxDriver(options);
        long end = System.currentTimeMillis();
        System.out.println((end - start)/1000 + "s");
            
        driver.get("about:profiles");
        //driver.quit();
    }
}
about:profile
ソースコード

やはり長時間(上の例では71秒)かかっています。
プロファイルに関しては、JavaとFirefoxDriver(geckodriver)の相性は悪いようです。

2021-01-09Selenium TipsFirefoxDriver,geckodriver,profile

Posted by sj