Seleniumを使ってIoT案件のSalesforce画面を画像に落とす
エンジニアの佐藤です。こんにちは。今回はSeleniumのお話をさせていただきたいと思います。
きっかけ
先週のこと、筆者はエビデンス(システム動作の証拠情報)画像を保存する作業を担当することになりました。 対象システムは、あるIoT案件のシステムです。データは多量にありますが、問題は作業時間です。 画面をひとつひとつ手作業でキャプチャして保存していたのでは長い時間を要します。 何かうまい方法はないものかと考えていた時、数年前に弊社のランチ勉強会 でSeleniumが取り上げられたのを思い出しました。今回はこれが効果的だろうと思って試してみました。
Seleniumとは
Seleniumとは、 Webブラウザをプログラムから操作する仕掛けです。 普段キー入力やクリックで実行しているブラウザ操作をコードを記述することで実行し、 またブラウザからHTML要素の値などを取得して評価することができます。 Webサイトのテストツールとして幅広く使われています。
実装方法
今回のエビデンス対象画面はSalesforceのオブジェクト詳細情報画面で
Canvas
を表示するページで、以下のようなレイアウトになっています。
この画面のURLは以下のような構造になっています。
https://apN.salesfoce.com/{Salesforce ID}
Salesforce IDはSalesforceオブジェクトそれぞれに発番されていますので、エビデンス画面の名称とSalesforce IDの対応表があれば、以下の処理フローが成立しそうです。
Salesforce IDからURLを生成 ↓ ブラウザでページを開く ↓ 画面名称からファイル名を生成して、ページ画像を保存
このフローをSeleniumで自動化できれば、あとは寝ているだけで網羅的な画像ファイル集ができあがるという算段です。
ではさっそく「エビデンス画面とSalesforce IDの対応表」を作成してみましょう。
いろいろな方法がありますが、筆者のおすすめはForce.com CLI
です。以下のようにコマンドを打つと、目的のCSVが取得できます。
$ force login -u=user@example.com -p=PASSWORD (ID、パスワードは仮) $ force query "SELECT Id, Name FROM XXX__c ORDER BY Name DESC" --format:csv > out.csv $ cat out.csv "Id","Name" "a099900000XXXXXXXX","20160321-4378" "a099900000XXXXXXXX","20160321-4377" "a099900000XXXXXXXX","20160321-4376" "a099900000XXXXXXXX","20160321-4375" "a099900000XXXXXXXX","20160321-4374" "a099900000XXXXXXXX","20160321-4373" "a099900000XXXXXXXX","20160320-4372" "a099900000XXXXXXXX","20160320-4371" "a099900000XXXXXXXX","20160320-4370" ...
次はこのCSVを読み込んでSeleniumを実行するプログラムの作成です。Seleniumはさまざまな言語で実装できますが、
今回は最もメジャーなJavaで作成しました。
今回もソースコード全体は弊社GitHub公開レポジトリ
で公開しています。
最初にCSVファイルを読み込んで、キーバリューペアの配列を作成します。(getIdNamesメソッド
。この部分はJavaの一般的な話なので、省略させていただきたいと思います。)
次にSeleniumを使ってSalesforceにログインします。以下のコードはSeleniumにFirefoxを起動させ、IDとパスワード文字列を打ち込んでログインボタンをクリックさせます。
WebDriver driver = new FirefoxDriver(); driver.manage().window().setSize(new Dimension(1200, 1600)); driver.get("http://login.salesforce.com/"); Thread.sleep(4000); driver.findElement(By.id("username")).sendKeys("user@example.com"); driver.findElement(By.id("password")).sendKeys("PASSWORD"); driver.findElement(By.id("Login")).click(); Thread.sleep(4000);
ログインが完了したら、いよいよCSVデータから作成したURLにナビゲートして画面を保存していきます。
private static void takeScreenOfId( WebDriver driver, String sfid, String name ) throws Exception { driver.navigate().to("https://apX.salesforce.com/" + sfid); Thread.sleep(12000); File scrFile = ((TakesScreenshot)driver).getScreenshotAs(OutputType.FILE); FileUtils.copyFile( scrFile, new File("/home/user01/Downloads/" + name + ".png")) ; } // end of takeScrenOfId
プログラムを実行すると、Firefoxが自動で動いて画面が移り変わっていきます。
一晩たってから確認してみると…目論見通りキャプチャ画像が保存されていました!
サーバー上で実行するには
Seleniumはブラウザを操作するプログラムであり、ブラウザは動作のためにデスクトップ画面を必要とします。ですので今回の話を手元のノートパソコンで実行すると、実行している間は画面を占拠されてしまい、仕事になりません。
この問題を解決する方法としては、サーバーに仮想デスクトップを設定する方法があります。仮想デスクトップ上でSeleniumプログラムを実行し、正常動作が確認されたらリモートデスクトップ接続を切ります。頃合いを見計らって再接続して、結果を確かめます。
仮想デスクトップの設定方法につきましては、過去ブログ「DockerでLinux仮想デスクトップサーバをつくる話」
などをご参照ください。
Salesforceのガバナ制限に注意
実は筆者はここで、思わぬ制限要因に引っかかってしまいました。対象ページはCanvasを使用しているため、 1ユーザにつき24時間で5,000回というSalesforceのガバナ制限 を超えてしまったのです。結果ある時点から先はすべてエラー画像ファイルとなり、やり直しでした。プログラム的なバッチ処理は、人が画面を使用する場合を大きく超えた思わぬリソース消費を伴うことがあります。注意したいポイントです。
コメント