GAE/GOでTwitter Botを作ってみる~後編~

  • このエントリーをはてなブックマークに追加

今回の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サービス仕様

http://weather.livedoor.com/weather_hacks/webservice

クエリパラメータ「city」に地域IDを指定することでその地域の天気情報を取得することができます。地域IDは以下RSSのURLから確認することができます。

http://weather.livedoor.com/forecast/rss/primary_area.xml

今回は東京の天気情報を取得してみましょう。ということで地域IDは「130010」です。これをREST APIのURLとして定義すると、東京の天気は以下URLから取得することができます。

http://weather.livedoor.com/forecast/webservice/json/v1 city=130010

REST APIのURLが確定したので、次はこのURLからデータの取得を行います。

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をパースする!

JSONのパースにはサードパーティパッケージの「jason」を利用します。まずは「jason」を以下のコマンドからダウンロードします。

$ go get github.com/antonholmquist/jason

プログラムを実装する前にパースするJSONを確認します。以下がAPIレスポンスのサンプルとなります。今回取得するパラメータは「publicTime」「title」「link」とします。

※ 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”, …}

それでは実装してみます。以下がJSONのパースを行うプログラムです。最初にjason.NewObjectFromBytes()を利用して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))
}

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)

前章で作成したTweet関数の中身をコメントアウトし、関数の中身を上記プログラムに差し替えてください。Tweet関数の編集後、goapp serveで開発サーバを起動します。

$ goapp serve twitter-bot

※「twitter-bot」は前章で作成したGAEアプリのルートフォルダです。前章から手順通りにBot作成を行っている場合は「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

上記設定によって毎朝11:00に「/tweet」のURL(前章で作成したプログラムのURI)がGAEから実行されるようになります。ただし、前述した通り、この設定はデプロイされない限りGAE上で実行されません。次はGAEへのデプロイの準備に入ります。

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を指定します。

application: <プロジェクトID>
version: 1
runtime: go
api_version: go1
handlers:
  url: /.*
 script: _go_app
 login: admin

※「login:admin」を指定することで外部からのアクセスを制限しています。この設定によってBotアプリのアクセスはアプリ管理者やcronによるアクセスに絞られます。
(2) 以下のコマンドを実行してGAEアプリケーションをデプロイします。

$ goapp deploy /path/to/project

※ goappはGAE/GO用のSDKに同梱されているツールです。「path/to/project」はGAEアプリ(プログラムファイルやapp.yamlが置かれているフォルダ)のパスを指定します。

(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.

デプロイしたら、あとはcron.yamlで設定した時間になるのを待つだけです。

※ ブラウザ等、外部から直接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サービスのサポートが可能です。

  • このエントリーをはてなブックマークに追加

Google のクラウドサービスについてもっと詳しく知りたい、直接話が聞いてみたいという方のために、クラウドエースでは無料相談会を実施しております。お申し込みは下記ボタンより承っておりますので、この機会にぜひ弊社をご利用いただければと思います。

無料相談会のお申込みはこちら