Selenium4に搭載されたCDPのAPIを叩いてブラウザの位置情報を上書きしてみた
みなさん、こんにちは
毎週末のベーグル作りがすっかり上達して楽しいのですが
家族のリアクションがだんだん薄くなってきていることに気づいた
自動化アーキテクトの森川です。
お客様のニーズを顧みない技術ドリブンには要注意ですね!
さてさて、少し前にSelenium4のRC版がリリースされたということで、α版から注目されているCDP機能を少し触ってみました。
Selenium 4 Release Candidate - Selenium
※ 本稿はJavaでお話を進めますが、Seleniumの言語バインディングは幅広く様々な言語でも書くことができます。
CDPのネイティブサポート
Selenium4ではChrome DevToolsAPIをネイティブサポートしており、以下の機能が利用できます。
・HTTPリクエストとHTTPレスポンスの監視と傍受
・ネットワーク速度のシミュレーション
・Basic認証
・Cookieとキャッシュ
・コンソールログとパフォーマンスメトリック
・位置情報のモッキング
などなど
Selenium4: A Peek into Chrome DevTools - by Deepak Attri - CodeX - Medium
Chrome デベロッパーツール - Selenium
位置情報のモッキングをためす
位置情報のモッキングを試してみました。
まずgradleの依存関係を設定します。
dependencies {
// selenium4
implementation 'org.seleniumhq.selenium:selenium-java:4.0.0-rc-1'
// jUnit
implementation 'org.junit.jupiter:junit-jupiter-api:5.6.0-M1'
implementation 'org.junit.jupiter:junit-jupiter-engine:5.6.0-M1'
}
WebDriver起動後にDevToolsのセッションを生成します。
driver = new ChromeDriver();
devTools = ((ChromeDriver) driver).getDevTools();
devTools.createSession();
Emulationを使って座標情報を作ってCDPに渡します。
devTools.send(Emulation.setGeolocationOverride(
Optional.of(35.25238415), # 経度
Optional.of(136.08378616), # 緯度
Optional.of(100))); # 精度
driver.get(BASE_URL);
サンプルページには某有名100均ショップの店舗検索ページを利用させていただきました。
大阪は道頓堀から
渋谷の松濤あたりへ、ひとっ飛び。
できました。
全体のソースはこちらです
class SeleniumTest {
private final String BASE_URL = "https://www.daiso-sangyo.co.jp/shop/map";
private WebDriver driver;
private DevTools devTools;
@BeforeEach
void setup() {
System.setProperty("webdriver.chrome.driver", "path_to/chromedriver.exe");
ChromeOptions chromeOptions = new ChromeOptions();
Map<String, Object> contentSettings = new HashMap<String, Object>();
Map prefs = new HashMap<String, Object>();
Map<String, Object> profile = new HashMap<String, Object>();
// シークレットモード+位置情報の扱いを許可
chromeOptions.addArguments("--incognito");
contentSettings.put("geolocation", 1);
profile.put("managed_default_content_settings", contentSettings);
prefs.put("profile", profile);
chromeOptions.setExperimentalOption("prefs", prefs);
driver = new ChromeDriver(chromeOptions);
driver.manage().timeouts().implicitlyWait(Duration.ofSeconds(600));
devTools = ((ChromeDriver) driver).getDevTools();
devTools.createSession();
}
@Test
void location道頓堀() throws IOException, InterruptedException {
devTools.send(Emulation.setGeolocationOverride(
Optional.of(34.6684533),
Optional.of(135.5013102),
Optional.of(100)));
driver.get(BASE_URL);
Thread.sleep(3000);
screenshot();
driver.quit();
}
@Test
void location渋谷() throws IOException, InterruptedException {
devTools.send(Emulation.setGeolocationOverride(
Optional.of(35.660856),
Optional.of(139.6908751),
Optional.of(100)));
driver.get(BASE_URL);
Thread.sleep(3000);
screenshot();
driver.quit();
}
void screenshot() throws IOException {
File file = ((TakesScreenshot) driver).getScreenshotAs(OutputType.FILE);
Files.copy(file.toPath(), new File("build/tmp/" + file.getName()).toPath());
}
}
このAPI、ユーザのアクセス地域でレスポンスが変わる機能のテストのようなユースケースでは有効かもしれませんね。
Handle permission pop-ups in Selenium tests - BrowserStack Docs
importしたパッケージにchromeのバージョンが含まれているのがちょっと気になりました。
import org.openqa.selenium.devtools.v92.emulation.Emulation;
Selenium3でもCDPってありましたよね?
Selenium3.x系でもありましたね。
ChromeOptionsのsetExperimentalOptionで指定可能です。
options.setExperimentalOption("mobileEmulation", <Emulation>);
つまりWebDriverを起動する前に設定しないといけないのですが、Selenium4では、WebDriver(ChromiumDriver)からCDPを操作できるようなりました。ブラウザを起動したままデバイスの表示サイズやUserAgentをコロコロと変えられるので、これは大きな違いだと思います。
他にも便利そうな機能が
CDPのAPIを眺めていると、ネットワークやCPUのエミュレーションなど、工夫すれば使えそうなものがいくつかありました。
こちらについては、あらためて試してみたいと思います。
・Chrome DevTools Protocol - Emulation domain
・Chrome DevTools Protocol - Network domain
__________________________________
お問合せはお気軽に
https://service.shiftinc.jp/contact/
SHIFTについて(コーポレートサイト)
https://www.shiftinc.jp/
SHIFTのサービスについて(サービスサイト)
https://service.shiftinc.jp/
SHIFTの導入事例
https://service.shiftinc.jp/case/
お役立ち資料はこちら
https://service.shiftinc.jp/resources/
SHIFTの採用情報はこちら
https://recruit.shiftinc.jp/career/