こんにちは、SIの楊です!
Seleniumを長期間で使用していると、特に頻繁に自動更新されるChromeブラウザにおいて、ドライバのバージョン不一致による問題が発生することがあります。
本記事では、この問題を解決するために調べたの二つの方法を紹介します。
方法1. CfTのAPIを使用して最新のChrome Driverを更新する
Chrome 115バージョンから、Googleはテストと自動化に特化した「CfT」ー「Chrome for Testing」をリリースしました。この新バージョンは、開発者が安定した環境でテストできるように、自動更新を管理し、特定のバージョンのChrome関連ファイルを提供します。
CfT(Chrome for Testing)のGitHubページでは、一連のJSON APIエンドポイントが提供されています。今回重要なのは、最新バージョンのダウンロードURLを取得できるlast-known-good-versions-with-downloads.json
のエンドポイントです。
このエンドポイントにアクセスすると、最新バージョンのChromeDriverのダウンロードURLを含むJSON情報が以下となります。
{
...
"channels": {
"Stable": {
"channel": "Stable",
"version": "124.0.6367.91",
"revision": "1274542",
"downloads": {
"chrome": [
...
],
"chromedriver": [
{"platform": "linux64", "url": "..."},
{"platform": "mac-arm64", "url": "..."},
{"platform": "mac-x64", "url": "..."},
{"platform": "win32", "url": "..."},
{"platform": "win64", "url": "..."}
],
"chrome-headless-shell": [
...
]
}
},
"Beta": {...},
"Dev": {...},
"Canary": {...}
}
}
先程のJSONを取得したら、解析を行い、対応するチャンネルとプラットフォームのURLを抽出することができます。
また、JSON内バージョンの情報も含めているので、バージョンをチェックする機能を追加することに、毎回実行する際にドライバを再ダウンロードする必要を避け、必要な時にのみ自動的にダウンロードすることができます。
以下の例は、ダウンロード機能のみとなります。
/**
* JSONデータから、特定のChromeDriverのダウンロードURLを取得するメソッド。
* @param jsonData JSON形式の文字列データ。
* @param channel チェックするチャンネル名(例:"Stable")。
* @param platform 対象のプラットフォーム(例:"win64")。
* @return ダウンロードURL。該当するURLが見つからない場合はnullを返す。
*/
private static String getDownloadUrl(String jsonData, String channel, String platform) {
// JSON文字列からJSONObjectを生成
JSONObject jsonObject = new JSONObject(jsonData);
// チャンネルとプラットフォームに基づいて、対象のドライバー情報を含むJSONArrayを取得
JSONArray drivers = jsonObject.getJSONObject("channels")
.getJSONObject(channel)
.getJSONObject("downloads")
.getJSONArray("chromedriver");
// JSONArrayをループして、指定されたプラットフォームに一致するURLを探す
for (int i = 0; i < drivers.length(); i++) {
JSONObject driver = drivers.getJSONObject(i);
if (driver.getString("platform").equals(platform)) {
return driver.getString("url"); // 一致するURLを見つけたら、そのURLを返す
}
}
return null; // 該当するプラットフォームのURLが見つからない場合はnullを返す
}
取得したURLを利用し、ChromeDriverのZIPファイルをダウンロードします。
/**
* 指定されたURLからファイルをダウンロードして、一時ファイルとして保存します。
* @param urlString ダウンロードするファイルのURL
* @return ダウンロードされたファイルへのFileオブジェクト
* @throws IOException 接続エラーやファイル操作の例外が発生した場合にスローされます
*/
public static File downloadFile(String urlString) throws IOException {
// URLオブジェクトを作成
URL url = new URL(urlString);
// URLへ接続
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.connect();
// 一時ファイルを作成
File tempFile = File.createTempFile("chromedriver", ".zip");
try (InputStream in = connection.getInputStream();
FileOutputStream out = new FileOutputStream(tempFile)) {
in.transferTo(out);
}
return tempFile; // 一時ファイルを返す
}
注意が必要なのは、この時点で取得しているのはドライバが含まれたZIPファイルであるため、ドライバを取得するにはファイルを解凍し、保存する必要があります。
方法2. WebDriverManagerのライブラリを使用する
WebDriverManager
は、Selenium WebDriverが必要とするドライバー(例:chromedriver、geckodriver、msedgedriverなど)のダウンロード、設定、維持を全自動で行うオープンソースのJavaライブラリです。(WebDriverManager
のGithubページより)
まずはMavenを使用する際、pom.xml
に WebDriverManager
のライブラリ情報の追加を行います。
もしChromeの更新によりエラーが出た場合はWebDriverManager
の Github リリースページをチェックして、最新のバージョンを使いましょう(2024年5月まではVersion 5.8.0
です)。
<project>
...
<dependencies>
<dependency>
<groupId>io.github.bonigarcia</groupId>
<artifactId>webdrivermanager</artifactId>
<version>5.8.0</version>
</dependency>
...
</dependencies>
</project>
そして、Javaで以下のコードを通じて最新のドライバーを使用できるようになります。
// ドライバーのセットアップを行います。
WebDriverManager.chromedriver().setup();
// Chromeの起動オプションを希望すれば、設定するためのオブジェクトを生成します。
ChromeOptions options = new ChromeOptions();
// Chromeドライバーのインスタンスを生成します。
WebDriver driver = new ChromeDriver(options);
これらの方法により、Chromeが更新されるたびに、対応するChromeDriverも自動的に更新され、自動化テストの連続性と安定性が保たれます。