読者です 読者をやめる 読者になる 読者になる

GoogleDriveAPIでHTMLファイルを作成し、GoogleドライブでWebサイト公開してアルクマを追いかける

GoogleAppsScript Google GoogleAppEngine

Advent Calendar in 信州松本(だけじゃなくてもいいよ)の18日目を担当しているthinkAmiです。


17日目はKenさんの「Highchartsを使って温度計を作ってみる」でした。
サーバーを運用していると温度・湿度は非常に気になるところなので、今すぐにでもこれを使ってサーバーの温度監視を分かりやすくしたいなぁと感じました*1。グラフ重要ですね。


さて、先月末、GoogleドライブにてWebサイト公開ができるようになったとのアナウンスがありました。
参考:Announcing Google Drive Site Publishing - Google Apps Developer Blog


そこで今回は、GoogleドライブにてWebサイト公開を行い、アルクマを追いかけてみます。



GoogleドライブでWebサイト公開するときの制限

  • HTMLやCSS、画像ファイルなどは問題なく動作するものの、JavaScriptが動作しない
  • URLが残念

この中のJavaScriptが動作しないというのが一番大きい制限であり、今回も使用するGoogleマップの形式はStaticMapsになりそうです。



全体の構成

アルクマのスケジュールは日々変更されるため、手動でHTMLファイルを作成・Googleドライブへアップロードするのは大きな手間です。
そこで、GoogleDriveAPIを用いてGoogleドライブ内にHTMLファイルを自動的に作成するようにします。
ただ、その場合はOAuthやDriveAPIの操作が必要になるため、その辺を簡略化できるPythonのライブラリを使用します。
参考:https://developers.google.com/api-client-library/python/reference/supported_apis


なお、アルクマのスケジュールデータについては、9日目で作成したGoogleカレンダーからデータを持ってくることにします。
本当はPythonのlxmlで解析する方が楽なのですが、GoogleAppEngineからGoogleカレンダーデータを扱いたかったため、あえてこの形式にしています。
そのため、構成図は以下の通りとなります。


Googleドライブ内の構成

www以下をWeb公開するため、wwwの共有設定で、「リンクを知っている全員が閲覧できます。」を選択しておきます。
また、cssファイルやpngファイルは、あらかじめGoogleドライブへと保存しておきます。今回、map.cssとshinanogold.pngは9日目のものを流用します。

root/
  www/
    css/map.css
    img/shinanogold.png
    index.html

事前準備

今回はGoogleDriveAPIとGoogleCalendarAPIを使うため、APIConsoleから両方を有効化します。
なお、似た名前にGoogleDriveSDKがありますが、APIとは別物なので、有効化は不要です。


また、APIを利用する場合、OAuthにて認証を行うため、9日目で使った「Client ID for web applications」の「Redirect URLs」に設定を行います。
今回は開発環境・本番環境の2箇所で利用するため、以下のように設定しました(URLが複数ある場合は、一行に1URLを指定します)。

http://arukumap.appspot.com/oauth2callback
http://localhost:8080/oauth2callback


なお、GoogleAppEngine用のライブラリを使う関係上、コールバックのURLは「oauth2callback」で固定となります。




app.yamlの設定

handlersに以下の設定を行います。
なお、認証後にパラメータを持ってリダイレクトされてくるため、HTML作成のハンドラは末尾を「.*」としておきます。

- url: /oauth2callback
  script: googledrivehandler.app
  login: admin

- url: /cron/googledrive.*
  script: googledrivehandler.app
  login: admin

OAuth用のOAuth2Decorator設定

client_id、client_secret、scopeを指定します。
今回はGoogleドライブとGoogleカレンダーへとOAuth認証後にアクセスするため、両方のOAuth用の設定をリストとして設定しておきます。

['https://www.googleapis.com/auth/drive', 'https://www.googleapis.com/auth/calendar']

参考:Google Drive SDK — Google Developers


GoogleAppEngineでファイルを作成する

GoogleAppEngine用のライブラリにある、「apiclient.http.MediaInMemoryUpload」を使用します。
ファイルの内容はMediaInMemoryUploadの第一引数に、ファイルのメタ情報はJSON形式にてそれぞれ指定します。
メタ情報のparentsのidにはフォルダのIDを指定しますが、フォルダのIDはブラウザのアドレスに表示される値を指定します。

media_body = MediaInMemoryUpload(arukuma.create_html(), mimetype='text/plain', resumable=True)
body = {
  'title': HTML_FILE_NAME,
  'description': 'A test document',
  'mimeType': 'text/html',
  'fileExtension': 'html',
  'parents': [
   {
    "id": apiKeys['folder_id'],
   }
  ],
}

drive_service.files().insert(body=body, media_body=media_body).execute()


HTMLファイル作成時のリテラルURIエンコードについては、以下を参考にしました。

GoogleDrive内のファイルを検索する

以下のような感じで、files().list()の引数qにファイル名「index.html」を指定し、対象のファイルIDを取得しています。
なお、デフォルトのままだとゴミ箱も検索対象のため、「trashed = False」とします。

query = 'title = "index.html" and trashed = False'
response = drive_service.files().list(q=query).execute()

参考:Google Drive SDK — Google Developers


ソースコード

GitHubへ18日目としてコミットしています。今回のメインは「googledrivehandler.py」ファイルです。
thinkAmi/ac2012matsumoto · GitHub


なお、google-api-python-clientライブラリも含まれていますので、ご注意ください。ライブラリのファイルやディレクトリは以下のものです。

  • apiclient
  • httplib2
  • oauth2client
  • uritemplate
  • gflags.py
  • gflags_validators.py

お願いなど

  • 静的な地図のため、場所へのリンクなどは行なっていません。
  • 場所から緯度・経度を求める際、Googleが変換できなかった場合には、アルクマの生息地へとマーカーを立てるようにしました
  • 相変わらずパフォーマンスについては考慮しておりません。
  • アルクマスケジュールのHTML構造が変わった場合には、こちらにスケジュールを反映できなくなるかもしれません。
  • GoogleCalendarAPI向けのパラメータでstartTime・endTimeパラメータがあったものの、今回は使用しませんでした。そのため、1月以降に影響が出そうです。

まとめ

3回にわたってGoogleのサービスでアルクマスケジュールを扱ってみました。実用的かどうかは分かりませんが、GoogleAPIに色々とさわったため、勉強になりました。
GoogleでWebサイトを公開する方法しては、他にはGoogleサイトがあります。こちらはよく紹介されているため、他のサイトをご確認ください。


次は

Advent Calendar in 信州松本(だけじゃなくてもいいよ)、明日はToro_Unitさんです。よろしくお願いします。

*1:先日も温度のアラートが出ました