Google Cloud Function + Cloud Scheduler + Python で定期的に Twitter 投稿する

## 概要

- Google Cloud Platform + Twitter API だけで完結するシステム構成とする
- Cloud Functions 上で Python のプログラムを定期実行して Twitter へ投稿する
- プログラミング言語には Python 3.7 を使用する
- Twitter へ投稿する Python のライブラリとして python-twitter を使用する
- 定期実行には Cloud Scheduler + Cloud Pub/Sub を使用する
- 動作環境や料金情報などは2019年8月16日現在の情報

## Cloud Functions とは

[Google Cloud Functions に関するドキュメント  \|  Cloud Functions  \|  Google Cloud](https://cloud.google.com/functions/docs/?hl=ja)

> Google Cloud Functions は軽量なコンピューティング ソリューションで、デベロッパーはサーバーやランタイム環境を管理することなく、Cloud イベントに応答する単一目的のスタンドアロン関数を作成することができます。

## Cloud Scheduler とは

[Cloud Scheduler  \|  Cloud Scheduler  \|  Google Cloud](https://cloud.google.com/scheduler/?hl=ja)

> Cloud Scheduler は、エンタープライズ クラスのフルマネージド cron ジョブ スケジューラです。

> Unix cron 形式でスケジュールを定義して、1 日に複数回ジョブを実行したり、1 年のうちの特定の日や月にジョブを実行したりできます。

## python-twitter とは

Twitter API を Python から使えるようにしたライブラリ。

- [python\-twitter · PyPI](https://pypi.org/project/python-twitter/)
- [GitHub \- bear/python\-twitter: A Python wrapper around the Twitter API\.](https://github.com/bear/python-twitter)

## Cloud Functions で関数を作成する

Google Cloud Platform にてプロジェクトを作成したら、左上のメニューから [Cloud Functions](https://console.cloud.google.com/functions?hl=ja) を選択する。

<img width="598" alt="google-cloud-functions-1.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139365/4f451029-4ccc-a285-a38b-c818b76c5311.png">

関数を作成する。

トリガーには「Cloud Pub/Cub」を指定する。
新しいトピックを作成して、名前をつける。Cloud Scheduler で使うため、わかりやすい命名をしたほうが良い。

<img width="720" alt="google-cloud-functions-2.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139365/382edea9-135a-ef69-cbe2-7016729460cf.png">

ソースコードをインラインエディタで入力する。

ランタイムには Python 3.7 を指定する。

<img width="434" alt="google-cloud-functions-3.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139365/4ff212c4-7366-d380-7d1e-3d00cfddc6e8.png">

main.py には以下の内容を入力する。

```python
import os
import sys
import time
import twitter

def get_twitter_api(credentials):
    return twitter.Api(
        consumer_key=credentials['consumer_key'],
        consumer_secret=credentials['consumer_secret'],
        access_token_key=credentials['access_token_key'],
        access_token_secret=credentials['access_token_secret'])

def hello_pubsub(event, context):
    try:
        api = get_twitter_api(os.environ)
        status = api.PostUpdate(f'Hello, world. {time.time()}')
        print(str(status))
    except:
        print(str(sys.exc_info()))
```

requirements.txt には以下の内容を入力する。

```
# Function dependencies, for example:
# package>=version
python-twitter
```

「環境変数、ネットワーキング、タイムアウトなど」をクリックすると、詳細オプションが表示される。

<img width="491" alt="google-cloud-functions-4.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139365/7c529b21-808d-71c3-c270-8e8e9f65b850.png">

ここでは環境変数を追加する。

Twitter API をコールするのに必要なパラメータをセットする。

<img width="472" alt="google-cloud-functions-5.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139365/2da7c2fe-5ae2-42fe-827d-1b827063bcfc.png">

「作成」ボタンを押すとプログラムがデプロイされる。

<img width="944" alt="google-cloud-functions-6.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139365/e8c35d4d-91f8-f1cb-3f98-e07ff07461d2.png">

右のメニューなどから関数のテスト画面へ移動する。
「関数をテスト」をクリックしてプログラムを実行できる。
エラーなどのメッセージは、「アウトプット」の項目ではなく、ログに出力される。

<img width="543" alt="google-cloud-functions-7.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139365/4b7ff3d6-14f2-37cc-c53e-f695bfffb082.png">

## Cloud Scheduler で定期実行を設定する

左上のメニューから [Cloud Scheduler](https://console.cloud.google.com/cloudscheduler?hl=ja) を選択する。

<img width="459" alt="google-cloud-scheduler-1.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139365/d0044a75-409e-b0f4-7df5-c493a8a636cb.png">

プロジェクトで最初のジョブを作成するときは、リージョンの選択が必要となる。
リージョンによっては使えないプロダクトがあるので注意。
参考: [ロケーション \- リージョンとゾーン  \|  Google Cloud](https://cloud.google.com/about/locations/?hl=ja)

<img width="544" alt="google-cloud-scheduler-2.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139365/1f7c8ac8-47e8-557d-ea56-1be385df446a.png">

ジョブを作成する。
頻度には、今回は10分おきに実行する設定「*/10 * * * *」を入力する。
ターゲットには Pub/Sub を指定する。
トピックには Cloud Functions で作成したトピック名を入力する。
ペイロードには関数に渡すデータを入力する。ここでは「{}」を入力する。

<img width="483" alt="google-cloud-scheduler-3.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139365/4d631160-13d0-68f9-6577-142160de45a6.png">

作成したジョブは「今すぐ実行」することも可能だし、設定した頻度でも実行される。
ジョブを実行すると、ターゲットを介して紐付けてある Cloud Functions の関数が実行される。

<img width="828" alt="google-cloud-scheduler-4.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139365/035561b7-fe3e-5ec9-14fa-ec028c8624c0.png">

10分おきの実行は頻繁なので、試し終わったらジョブを削除しておいたほうが良い。

## 料金について

[料金  \|  Cloud Functions のドキュメント  \|  Google Cloud](https://cloud.google.com/functions/pricing?hl=ja)

> 呼び出し料金は 1 回あたり \$0.0000004 の単価制で、関数の結果や使用期間に関係なく請求されます。ただし、毎月最初の 200 万回までは無料です。

> Cloud Functions にはコンピューティング時間リソースを永久的に無料で使える階層があり、GB 秒と GHz 秒の両方の割り当てが含まれています。無料階層には 200 万回の呼び出しのほかに、400,000 GB 秒、200,000 GHz 秒のコンピューティング時間と、1 か月あたり 5 GB のインターネット下りトラフィックも含まれています。無料階層を使用する場合でも、有効な請求先アカウントが必要です。

[料金  \|  Cloud Scheduler のドキュメント  \|  Google Cloud](https://cloud.google.com/scheduler/pricing?hl=ja)

> Cloud Scheduler の料金は「ジョブ」を基準に計算されます。Cloud Scheduler のジョブは、定義された頻度で行うようにスケジュールした 1 つのアクティビティのことを指します。
> 
> 実際にジョブを行うことを「実行」と呼びます。ジョブは個々の実行単位で課金されることはありません。たとえば、1 つのジョブを「1 か月間毎日」行うように定義しても、そのジョブの 30 回の実行について月額 \$3 が課金されるのではなく、全体として月額 \$0.10 が課金されます。

> Google アカウントごとに、毎月 3 つのジョブを無料で利用できます。この無料枠は、プロジェクト レベルではなくアカウント レベルで集計されるので注意してください。たとえば、アカウントに 5 つのプロジェクトがあり、各プロジェクトに 2 つのジョブがある場合、無料のジョブは 3 つ、有料のジョブは 7 つになります。

[料金  \|  Cloud Pub/Sub ドキュメント  \|  Google Cloud](https://cloud.google.com/pubsub/pricing?hl=ja)

> メッセージのパブリッシュまたは配信の料金は TiB あたり \$40 で、階層はありません。また、リージョン内の下りデータに対する料金が導入されました。インターネットの下り料金と GCP リージョン間でのインターネット配信の料金は、ゾーンの下りと Google サービスへの下りを除き、Compute Engine のネットワーク料金と同様です。Cloud Pub/Sub の使用に対するゾーンの下り料金は発生しません。Google サービスへの下りは下り料金の対象となります。たとえば、1 MiB のメッセージを us-west1 にパブリッシュし、europe-west1 のサブスクライバーに配信すると、2 つの SKU 間で合計 3 MiB の料金が課金されます。基本的なメッセージ配信で 2 MiB（パブリッシュと配信に 1 MiB ずつ）とアメリカ大陸から EMEA へのリージョン間のデータ配信で 1 MiB が課金対象になります。

## 参考資料

- [Pub/Sub を使用して Cloud ファンクションをトリガーする  \|  Cloud Scheduler のドキュメント  \|  Google Cloud](https://cloud.google.com/scheduler/docs/tut-pub-sub?hl=ja)
- [cron ジョブ スケジュールの構成  \|  Cloud Scheduler のドキュメント  \|  Google Cloud](https://cloud.google.com/scheduler/docs/configuring/cron-job-schedules?hl=ja)