面倒な定期データ集計をGoogleスプレッドシートに自動で書き出して共有を楽にする

こんな事ありませんか？
例えば「Playerの登録数を毎日確認したいからエクセルか何かに書き出してほしい」 と頼まれたりとか。
私は良く有ります。
今までは、律儀に1日一回集計コマンドを実行して、集計結果をエクセルにコピペみたいな事をしていた事もありました。
そんなの面倒くさいですよね？
なので、そんな面倒な事はやめにして、自動化しちゃいましたというお話。

そこで、表計算出来た方が何かと便利ですが、エクセルだと面倒なのでgoogleスプレッドシートに集計結果を毎日自動で書き込む「集計君」を作る事にしました。


# googleサービスアカウントの作成
まずはすプレッドシートをAPI操作する為にgoogleサービスアカウントを作成します。

## 新規プロジェクトの作成
まず、google Developers Consoleにアクセスし、新規プロジェクトを作成します。

<img width="766" alt="スクリーンショット_2016-04-10_22_47_12.png" src="https://qiita-image-store.s3.amazonaws.com/0/93763/88685d95-a7ee-bc7c-8453-8d941556ea79.png">

## Drive APIを有効化
プロジェクトが作成できたら、作成したプロジェクトを選択し、googleAPIsのアイコンで下記ページに遷移します。
次にDrive APIを選択します。
<img width="1659" alt="スクリーンショット_2016-04-10_22_46_32.png" src="https://qiita-image-store.s3.amazonaws.com/0/93763/85a86786-4896-7cc8-1974-280bc8ab459d.png">

APIを有効化します。
<img width="971" alt="スクリーンショット_2016-04-10_22_53_02.png" src="https://qiita-image-store.s3.amazonaws.com/0/93763/af716195-cc7e-9164-904d-388aa1582812.png">

## サービスアカウントの作成
API Managerから認証情報ページに遷移しサービスアカウント作成を選択します。
<img width="960" alt="スクリーンショット_2016-04-10_23_05_01.png" src="https://qiita-image-store.s3.amazonaws.com/0/93763/d7a08f3a-2452-07db-98aa-b75d2e323aa5.png">

## P12ファイルを作成する
対象のEngineを選択し、認証用のP12ファイルを作成します

* Google App Engine : googleDriveなどのクラウド上のサービスを使用する場合に選択
* Google Compute Engine : 「Google Compute Engine 」というgoogleが提供する仮想サーバーを使用する場合に選択

今回はGoogle App Engineを使用します。

<img width="490" alt="スクリーンショット 2016-04-10 23.14.38.png" src="https://qiita-image-store.s3.amazonaws.com/0/93763/efb2a0c3-b3f4-aeea-a341-0a3a85e9367b.png">

作成を押すとP12ファイルがダウンロードされて、パスワードが表示される。
<img width="1060" alt="スクリーンショット_2016-04-10_23_19_15.png" src="https://qiita-image-store.s3.amazonaws.com/0/93763/693cf6f7-2353-feee-6182-9cf9502c15b4.png">

詳細情報ではApp EngineにキーIDが割り振られている事が確認できます。
これでサービスアカウントの作成が完了です。
<img width="1400" alt="スクリーンショット_2016-04-10_23_37_06.png" src="https://qiita-image-store.s3.amazonaws.com/0/93763/9d62b674-828f-f6c7-f761-7c1c12c53302.png">


# スプレッドシートの操作
次に作成したサービスアカウントからスプレッドシートを編集していきます。

##サービスアカウントを共有
操作したい、スプレッドシートを開き、サービスアカウントを共有します。
<img width="631" alt="スクリーンショット_2016-05-01_22_08_18.png" src="https://qiita-image-store.s3.amazonaws.com/0/93763/054f330d-f2c1-90fa-fa37-4ad817ad0936.png">

共有方法は通常のユーザー登録と同じです。
先ほど作成したサービスアカウントのメールアドレスを編集者として登録します。
<img width="597" alt="スクリーンショット_2016-04-10_23_41_49.png" src="https://qiita-image-store.s3.amazonaws.com/0/93763/631c20c7-a6aa-5e49-63f1-5439bd881692.png">

##スクリプトの作成

下記は例ですが、実際は必要な処理を行い、指定したcellに必要な値を書き込みます。
下記モジュールをpip install してください。

* oauth2client : oauth2認証を行う為のモジュール
* gspread : スプレッドシートを操作する為のモジュール
    * [gspreadの使い方はこちらの記事が参考になります](http://www.yoheim.net/blog.php?q=20160205)

```py

# -*- coding: utf-8 -*-
from oauth2client.client import SignedJwtAssertionCredentials
import gspread
import MySQLdb
import datetime


# ======auth======
EMAIL = 'xxxxxxx@xxxxxxxxx.serviceaccount.com' #サービスアカウントのアドレス
SECRET_KEY_PATH = '/home/xxxxxxxxx.pem' #サービスアカウント作成時に発行したp12ファイルを変換したもの(後述)

# ======sheet======
WORK_BOOK_KEY = 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'  # URLに書いてあるKEY
WORK_SHEET_NAME = 'xxxxxxxxxxxxxxxxxx' #シートの名前

# ======database======
DB_HOST = 'localhost'
DB_USER = 'root'
DB_PASS = ''
DB_NAME = ''


def get_credentials():
	client_email = EMAIL
	f = open(SECRET_KEY_PATH) 
	private_key = f.read() 
	scope = ["https://spreadsheets.google.com/feeds"]
	return SignedJwtAssertionCredentials(client_email, private_key, scope=scope)
	
	
def get_value():
	summary_datetime = datetime.datetime.now()
	conn = MySQLdb.connect(host=DB_HOST, user=DB_USER, passwd=DB_PASS, db=DB_NAME)
	cursor = conn.cursor()
	try:
		query = 'select count(id) from table where created_at < \"{datetime}\"'.format(datetime=summary_datetime)
		cursor.execute(query)
		value = cursor.fetchone()
	finally:
		cursor.close()
		conn.close()
	return value


if __name__ == "__main__":
	#認証
	credentials = get_credentials()
	
	row_index = 1 
	col_index = 1
	
	#DBから値取得
	value = get_value()
	
	# シートの取得
	gc = gspread.authorize(credentials)
	wb = gc.open_by_key(WORK_BOOK_KEY)
	sheet =  wb.worksheet(WORK_SHEET_NAME)
	sheet.update_cell(row_index, col_index, value)
```

##oauth2clientのバージョンに注意
上記のスクリプトを参考にした場合oauth2client2系だとエラーになるので、1.5.2して解決。

##p12ファイルの変換
p12ファイルの指定でエラーになる。
単純にファインダーで拡張子を書き換えても有効にならないので、下記コマンドでpemファイルを作成。

```
openssl pkcs12 -in xxxxxxxxxxxxx.p12 -nodes -nocerts > xxxxxxxxxx.pem
```
変換時に要求されるパスワードはP12ファイル作成時に表示されていたパスワードを指定します。


# まとめ
これで、準備が整ったので、プログラムを使ってスプレッドシートに書き込む事ができます。
crontabなどで定期的に実行してあげる事で、自動で集計できるので、非常に便利です。

今回API操作を試みるまでは、スプレッドシートを外部から操作するのは結構難しそうなイメージがありましたが、やってみたら意外に簡単にできたなーって印象です。

ちなみに、今回は説明を省きましたが、自分は上記プログラムが実行された際に、hipchatにメッセージを投稿する機能も付けています。
そうする事で更新された際にチャットに連絡が来るので、分かりやすくなります。

今も毎日手動で心暖まる集計を行っている人がいたら、今回の様に是非自動化を試みては如何でしょう。^^