今回のapps-gcpは「GAE/GOでTwitter Botを作ってみる」の後編記事です。前編記事では、Twitterアプリの登録方法からローカル環境でTwitter投稿するまでの手順について説明しました。後編ではいよいよ、お天気情報を定期時間に自動で呟くTwitter botを作成します。後編の記事内容は以下の通りです。
後編
※ 前編記事のURLは以下の通りです。
https://apps-gcp-tokyo.appspot.com/gae-go-twitter-bot-1/
それではTwitter botを作成していきましょう。
目次
GAE/Goで天気予報botを実装する!!
東京の天気を取得するためのREST APIのURLを決定する!
天気情報はLivedoorのお天気WebサービスのAPIから取得します。
まずは天気予報情報を取得するためのREST APIのURLを特定しましょう。
-お天気Webサービス仕様
今回は東京の天気情報を取得してみましょう。ということで地域IDは「130010」です。これをREST APIのURLとして定義すると、東京の天気は以下URLから取得することができます。
http://weather.livedoor.com/forecast/webservice/json/v1 city=130010
GAEでREST APIからレスポンス(JSON)を取得する!
それでは実装してみましょう。GAEから外部APIへのhttpリクエストを送信するためにはurlfetchを利用します。まずはurlfetchで取得したJSONをログ出力するコードを実装します。前編で説明した手順で以下のプログラムをローカル環境で実行してみましょう。以下を実行すると、単純にJSONデータがコンソール上に出力されます。
ctx := appengine.NewContext(r)
client := urlfetch.Client(ctx)
req, err := http.NewRequest("GET", "http://weather.livedoor.com/forecast/webservice/json/v1 city=130010", nil)
if err != nil {
panic(err)
}
resp, err := client.Do(req)
if err != nil {
panic(err)
}
body, err := ioutil.ReadAll(resp.Body)
ctx.Infof("%s", string(body))
}
レスポンスJSONをパースする!
JSONのパースにはサードパーティパッケージの「jason」を利用します。まずは「jason」を以下のコマンドからダウンロードします。
$ go get github.com/antonholmquist/jason
※ descriptionはTwitterの140文字制限に抵触してしまうため今回は取得しません。
{
"publicTime" : "2013-01-29T11:00:00+0900",
"title" : "東京都 東京 の天気",
"description" : {
"text" : " 北日本は高気圧に覆われています。 一方、低気圧が黄海にあって、東北東へ進んでいます。 【関東甲信地方】 関東甲信地方は、晴れまたは曇りとなっています。 17日は、はじめ高気圧に覆われて晴れますが、日本海を北東へ進む低気圧に向かって南海上から湿った空気が入るため次第に曇りとなり、夕方から雨となる見込みです。 甲信地方では夜遅く雷を伴い激しい雨の降る所があるでしょう。 18日は、日本海を北東へ進む低気圧の影響で午前中は雨となり、雷を伴い激しい雨の降る所がある見込みです。 午後は次第に曇りや晴れとなるでしょう。 関東近海では、17日は波が高く、18日はしけるでしょう。 また、所々で霧が発生しています。 船舶は高波や視程障害に注意してください。 【東京地方】 17日は、晴れ後曇りで、夕方からは雨となるでしょう。 18日は、雨が降りますが、昼過ぎからは曇りとなるでしょう。",
"publicTime" : "2013-01-29T10:37:00+0900"
},
"link" : "http://weather.livedoor.com/area/forecast/400040", …}
ctx := appengine.NewContext(r)
client := urlfetch.Client(ctx)
req, err := http.NewRequest("GET", "http://weather.livedoor.com/forecast/webservice/json/v1 city=130010", nil)
if err != nil {
panic(err)
}
resp, err := client.Do(req)
if err != nil {
panic(err)
}
body, err := ioutil.ReadAll(resp.Body)
ctx.Infof("%s", string(body))
}
v, _ := jason.NewObjectFromBytes([]byte(string(body)))
publicTime, _ := v.GetString("publicTime")
ctx.Infof("%s", publicTime)
title, _ := v.GetString("title")
ctx.Infof("%s", title)
link, _ := v.GetString("link")
ctx.Infof("%s", link)
$ goapp serve twitter-bot
開発サーバを起動後、以下のcurlコマンドを実行します。
$ curl http://localhost:8080/tweet
2017/04/07 05:26:30 INFO: 2017-04-07T11:00:00+0900
2017/04/07 05:26:30 INFO: 東京都 東京 の天気
2017/04/07 05:26:30 INFO: http://weather.livedoor.com/area/forecast/130010
パースしたパラメータを結合してTwitterに投稿する!
次に取得した「publicTime」「title」「link」を文字列結合し、Twitterに投稿するコードを実装します。Twitterに投稿するコードは前編で実装したコードを利用します。
// ConsumerKeyのセット
anaconda.SetConsumerKey(consumerKey)
// ConsumerSecretのセット
anaconda.SetConsumerSecret(consumerSecret)
// AccessTokenとAccessTokenSecretのセット
api := anaconda.NewTwitterApi(accessToken, accessTokenSecret)
// apiのHttpClient.TransportにurlfetchのTransportを利用する
api.HttpClient.Transport = &urlfetch.Transport{Context: ctx}
values := url.Values{}
// ツイートする
_, err = api.PostTweet(publicTime + " " + title + " " + link, values)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
}
以上で天気情報の自動投稿botの作成は完了です。実際にローカル環境で動作させることで動作を理解しましょう
※ consumerKeyとaccessToken情報については、前編で作成した値をセットしてください。
package main
import (
"net/http"
"github.com/ChimeraCoder/anaconda"
"appengine/urlfetch"
"appengine"
"io/ioutil"
"github.com/antonholmquist/jason"
"net/url"
)
const (
consumerKey = "**************************"
consumerSecret = "**************************"
accessToken = "**************************"
accessTokenSecret = "**************************"
)
func init() {
http.HandleFunc("/tweet", Tweet)
}
func Tweet(w http.ResponseWriter, r *http.Request) {
ctx := appengine.NewContext(r)
client := urlfetch.Client(ctx)
req, err := http.NewRequest("GET", "http://weather.livedoor.com/forecast/webservice/json/v1 city=130010", nil)
if err != nil {
panic(err)
}
resp, err := client.Do(req)
if err != nil {
panic(err)
}
body, err := ioutil.ReadAll(resp.Body)
ctx.Infof("%s", string(body))
v, _ := jason.NewObjectFromBytes([]byte(string(body)))
publicTime, _ := v.GetString("publicTime")
ctx.Infof("%s", publicTime)
title, _ := v.GetString("title")
ctx.Infof("%s", title)
link, _ := v.GetString("link")
ctx.Infof("%s", link)
// ConsumerKeyのセット
anaconda.SetConsumerKey(consumerKey)
// ConsumerSecretのセット
anaconda.SetConsumerSecret(consumerSecret)
// AccessTokenとAccessTokenSecretのセット
api := anaconda.NewTwitterApi(accessToken, accessTokenSecret)
// apiのHttpClient.TransportにurlfetchのTransportを利用する
api.HttpClient.Transport = &urlfetch.Transport{Context: ctx}
values := url.Values{}
// ツイートする
_, err = api.PostTweet(publicTime + " " + title + " " + link, values)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
}
}
GAEでスケジューリング(cron)設定をおこなう!
次は前章で作成した投稿プログラムを定期実行するためのスケジューリング設定をおこないます。「特定の日時になったらバッチプログラムを実行する」「1時間毎にレポートメールを送信する」といった自動定期処理をGAEから実行したい場合は、GAEのcron機能を利用します。cron機能を有効化するのはとても簡単で、cron.yamlにスケジューリングの設定を定義しデプロイを実行するだけです。
前章で作成したGAEプロジェクトフォルダ直下にcron.yamlというファイルを作成し、以下の内容をコピペします。
cron:
- description: tweet weather news
url: /tweet
schedule: every day 11:00
timezone: Asia/Tokyo
GCPプロジェクトを作成する!
GAEアプリケーションをデプロイするためにはGCPプロジェクトを作成する必要があります。GCPプロジェクトの作成手順がわからない場合は以下URLをご参考ください。
– 初心者のためのGCPプロジェクト始め方入門
https://apps-gcp-tokyo.appspot.com/gcp-startup/
登録したTwitterアプリの設定データ(WebSite)を変更する!
前章でTwitterアプリを登録した時に「WebSite」の項目には「この時点では何でも良いので適当なURLを指定してください」と記載しました。それは、Twitterアプリ登録時点でGAEアプリのURLが決定していなかったからです。GAEのURLはプロジェクトのIDによって決まるため、前章でプロジェクトを作成していればURLを登録できる状態となります。
-Twitter Apps
https://apps.twitter.com/
上記URLから前章で作成したTwitterアプリを編集し「WebSite」に以下のURLを入力しアプリデータを更新してください。
http://<作成したプロジェクトのID>.appspot.com
GAEにアプリケーションをデプロイする!
それでは、いよいよデプロイの準備が整いました。以下の手順に従ってGAEアプリのデプロイを実行してください。
(1) 前章で作成したapp.yamlを編集し<プロジェクトID>に作成したGCPプロジェクトのIDを指定します。
version: 1
runtime: go
api_version: go1
handlers:
url: /.*
script: _go_app
login: admin
(2) 以下のコマンドを実行してGAEアプリケーションをデプロイします。
$ goapp deploy /path/to/project
(3) 「Deployment successful.」と表示されればデプロイは成功です。
…
3:59 PM Cloning 49 application files.
03:59 PM Compilation starting.
03:59 PM Compilation: 46 files left.
03:59 PM Compilation completed.
03:59 PM Starting deployment.
03:59 PM Checking if deployment succeeded.
03:59 PM Deployment successful.
03:59 PM Checking if updated app version is serving.
03:59 PM Completed update of app: morita-demo, version: 1
03:59 PM Uploading cron entries.
※ ブラウザ等、外部から直接URL(http://○○○○.appspot.com/tweet)にアクセスしたい場合はBotアプリ(GAEアプリ)の管理者になる必要があります。アプリの管理者であれば、Google認証によってcronが実行する前にプログラムの実行が可能です。
botの動作をGAEのサーバ上で確認する!
cron.yamlで指定した時間になったらTwitterを確認してみましょう。指定通りの時間に以下のようなツイートが投稿されているはずです!!
これでbotプログラムのデプロイは完了です!これで毎日同じ時間になると天気情報がツイートされるようになります!!
GAE/Goで Twitter Bot作成のまとめ
以上で天気予報を自動ツイートするbotの作成は完了です。今回取り扱ったサンプルコードはコピペすればGAE上で動作するコードになっています(トークン情報やアプリケーションIDの書き換えは必要です)。ですので、そのまま動作させるのも良いですし、自分用のbotになるように簡単な所では地域コード等修正を加えてみるのも良いかもしれません。
ちなみにこの程度の内容のプログラムであれば、GAEでは無料で運用することが可能です(これでも無料クオータを持て余してしまうくらいです)。ぜひ今回作成したbotプログラムをキッカケにGCPの世界に飛び込んでみてください!!
※ 弊社ではクラウドエース(Cloud Ace)というGCPの導入・運用支援サービスを提供しておりますので、ご興味のある方はこちらまでお問い合わせください。GAEに限らず、あらゆるGCPサービスのサポートが可能です。