Google Apps Script 入門: Web 上の画像をGoogle Drive に保存する

たまたま Google App Script (以下、GAS)を使う機会があったので、今回は GAS を使って遊んでみる。

GAS のための環境準備

といってもほとんどない。最低限、Google アカウントとブラウザがあれば事足りる。

Google Apps Script
Create and edit scripts

とりあえず、Chrome にこれをいれておく。
そうすると、アプリに「Google Apps Script」が追加される。
これをクリックすると、ブラウザ上で専用のエディタが表示され、すぐにスクリプトを作成することができる。

また、以下の拡張機能は Chrome に入れておくといい感じだった 。

Google Apps Script GitHub Assistant
Manage your gas code with github/github enterprise/bitbucket/gitlab
AppsScript Color
This extension change the color style of the google apps script editor. It also allow to use folders with folder/subFolder/file

前者は GAS のコードをブラウザ上で github 連携するもの、
後者はスクリプトエディタのカラーテーマ変更。

導入

GAS 自体は普通の JavaScript。
API に関しては以下で細かくクラス・関数の説明がある。

Reference Overview  |  Apps Script  |  Google Developers

スクリプトを書いたら、コンボボックスで実行したい関数を選択して、実行ボタン。


ブレークポイントをはってデバッグ実行することもできる。

2つのログ出力方法

  Logger.log("I love miku.");
  Logger.log("I love %s.", "miku");

Logger クラスの実行結果は、「表示」→「ログ」で直前の実行結果を表示できる。

ただ、この場合、直前の結果しか表示されず、履歴は残らない。
もし、履歴を残したい場合は、console を使用する。

Class console  |  Apps Script  |  Google Developers
  console.log("I love miku.");
  console.warn("I love %s.", "miku");

「表示」→「Stackdriver Logging」か、ログ表示中の「Apps Script ダッシュボード」のリンクをクリックすると、以下のようなページが開き、それぞれ履歴を含めてログを参照できるようになっている。

この Stackdriver というのは無料版・有料版があるが、無料版でも1プロジェクトあたり1ヶ月に50GB までログ取り込みが可能なので十分使える。

Logger の場合、エディタ上でログ画面を開きながら実行というのができない 。

が、console を使えば別窓で開いておけばすぐに確認できるし履歴も残る。
なので基本的には console 使っておけばいいと思う。

PropertiesService

WebAPI を使う場合、発行されたトークンや ID 等を定数として使用するケースが多いと思う。
PropertiesService を使うと、以下のように、事前に外部で定数を指定しておいて、実行時に プログラム側から値を読み込むことができる。

「ファイル」→「プロジェクトのプロパティ」→「スクリプトのプロパティ」を選択し、必要な定数を定義しておく。

プログラム側から配下のようにして読み込みが可能。

var FOLDER_ID = PropertiesService.getScriptProperties().getProperty('folder_id');
if (!FOLDER_ID) {
    throw "folder_id" property is undefined;
}

DriveApp によるファイル操作

GAS を利用してなにかしたいという場合、大抵は Google Drive にアクセスして何かを参照したり保存したりするのに使うことが多いと思う。
その場合、DriveApp クラスによくお世話になる。

Class DriveApp  |  Apps Script  |  Google Developers

例えば、以下は任意のフォルダを探索し、もしなければ作成して返す関数の例。

function FindOrCreateFolder(folderName) 
{
  // 指定 ID のフォルダを取得する
  // (ID はそのフォルダの URL https://drive.google.com/drive/folders/XXXX の XXXX の部分がフォルダ ID)
  var folder = DriveApp.getFolderById(FOLDER_ID);
  var itr = folder.getFoldersByName(folderName);
  if( itr.hasNext() )  {
    // フォルダが見つかった場合はそれを返す
    return itr.next();
  }
  // フォルダが見つかった場合は作成して返す
  var newFolder = folder.createFolder(folderName);
  newFolder.setName(folderName);
  return newFolder;
}

なお、DriveApp などは、初回実行時に以下のようなリクエストを求めてくる場合があるので許可しておくこと。

画像を GoogleDrive に保存

で、タイトルどおり、GAS で GoogleDrive に Web 上の画像ファイルを保存してみる。
例えば、以下のようなコードを書けば良い。

function Download(saveFolder, url)
{
  // url を指定してファイルを受け取る
  var response = UrlFetchApp.fetch(url);
  console.log("Download: " + url + "\n => " + saveFolder.getName());

  // Google Drive で保存するファイル名をセット
  var fileName = url.split('/').pop();
  var fileBlob = response.getBlob();
  fileBlob.setName(fileName);
  
  // ファイル名がかぶっていたら、前のものは削除する
  // (Google Drive の場合、名前がかぶっていても上書き対象にはならない)
  var itr = saveFolder.getFilesByName(fileName);
  if( itr.hasNext() ) {
    saveFolder.removeFile(itr.next());
  }
  // 新規ファイルとして保存
  return saveFolder.createFile(fileBlob);
}

function TestSaveFile()
{
  var url = "https://sonicwire.com/images/sp/cv/mikuv4xb_img1.jpg";
  
  var folder = FindOrCreateFolder("Img");
  var file = Download(folder, url);
}

実行した結果↓

使ってみた感想

個人的に使ってみて便利だなーと感じたこと。

  • データベースやサーバなしにデータ収集ができる
  • 作ったスクリプトに対して、定期実行を設定することができる
  • ブラウザ上で完結していて、さくっと試すことができてすこぶる便利
  • 大量のデータを扱うようなケースでは API の制限があるので注意が必要