この記事は [Stylez Advent Calendar 2018] (https://qiita.com/advent-calendar/2018/stylez) の 24日目の記事です。メリークリスマス!
(仏滅だけど、アドベントカレンダーで空いている日はここしかなかったw←無駄に大安にこだわっている)
本記事は、
の続きです!
①以前からAPIで何かするってことをしたかった。
②現在勉強中のPythonでなんか作ってみたかった。
③Lambdaを使って何かできないかな~、サーバレスかっちょいいと思った。
④今晩作るおすすめレシピをゲットできたら良いな~と思った
という動機のもと、
非エンジニアが
「PythonとAWS Lambdaを使ってAPIで取得したデータをTwitterに自動でつぶやく」ことに挑戦しています。
本記事は、
Pythonを活用して楽天レシピAPIの取得情報をTwitterに投稿するコード作成~
AWS Lambdaを動かしてTwitterに自動投稿までです。
##前回までに試してみたこと
- Pythonのrequestsを使ってAPI情報を取得
- 楽天レシピAPIから人気メニュー情報を表示
- TwitterAPIを利用して楽天レシピから取得したデータを投稿
今後の構想として、以下をあげさせていただきました。
- Lambdaで、Twitterに自動投稿 ←今回の記事
##Lambdaで動かすためのPythonコードを作成する
とりあえず、今までのコードでは、
Lambdaでは動いてくれなそう。。という野生的感が働き、
「Python Lambda Twitter」 などで検索しまくる
以下の記事を参考に
Pythonコードを作成しなおしました。
AWS LambdaでMOCO'Sキッチンの更新情報をつぶやくTwitter Botを動かす
「def でハンドラー内に、実行内容を書けばよいんだろう!」
と
「returnというものを使わなきゃいけないらしい!」
ということだけを習得し、
Anacondaでソースコード作成。
今回はクリスマスっていうこともあるので、
「クリスマスにおすすめのレシピ」カテゴリーからメニューを取得♪♪
import twitter
import requests
url = 'https://app.rakuten.co.jp/services/api/Recipe/CategoryRanking/20170426?applicationId=XXXXXXXXXXXXXXX&categoryId=50'
api_data = requests.get(url).json()
def getmenu():
for menu in api_data['result']:
if menu['rank'] == ('3'):
menu_title = menu['recipeTitle']
menu_url = menu['recipeUrl']
recipe = menu_title + menu_url
return recipe
def lambda_handler(event, context):
auth = twitter.OAuth(consumer_key="XXXXXXXXXXXXXXX",
consumer_secret="XXXXXXXXXXXXXXX",
token="XXXXXXXXXXXXXXX",
token_secret="XXXXXXXXXXXXXXX")
t = twitter.Twitter(auth=auth)
t.statuses.update(status = getmenu())
if __name__ == '__main__':
lambda_handler(None, None)
めちゃくちゃ汚いコードだと思いますが
完成!!
(これでも四苦八苦した)
(defの実行結果としてreturnで設定しなきゃいけない掟とか、よくわかんなかった。いまだによくわかっていない)
次はLambdaに登録しようとしたけど、
ここですごくつまづきました。
##AWS Lambdaで使う外部モジュールはzipで登録しなきゃらしい
AWSのWEBコンソールからLambdaを選択。
Lambadaを扱う新規ロールを作成して、Lambdaの関数を登録する画面までたどりつく。
Lambdaの関数を登録するまでの基本的なWEB画面(コンソール)の操作方法は、
やはり以下の記事を参考にさせていただきました。
AWS LambdaでMOCO'Sキッチンの更新情報をつぶやくTwitter Botを動かす
で、問題はここから。
LambdaのWEB画面からコードを編集してたけど、
どうやら外部モジュールはzipにしてアップしなきゃいけないということらしい。
(ここに気づくまで、結構時間かかった。
LINUX使うことが前提になっている記事が多いけど、こちらの環境はWindowsローカル。
zipするまでの操作方法は黒い画面で皆さんしているようだけど、
私にとってはAnacondaみたいにWEBのコンソールに登録するほうが簡単じゃん、と思ってしまった)
「ううう、、」
と思いながら、ローカルの該当ディレクトリに実行モジュールをインストールする方法を探す。
power shell で
mkdir workspace
cd workspace
pip install requests -t .
pip install twitter -t .
無事、作成したworkspaceディレクトリにファイルがいっぱいダウンロードされていました。
しかーし、ここで問題発生
powershellでzipコマンド使えない。
なぜなのかー
##Windowsローカル環境のファイルをどうやってzipにするの?
zipってあのzipだよね?
自分のWindowsに入れているLhaplusで圧縮して、
Lambdaにアップロード。。。
できない!!
ずっとアップロード中です〜、みたいなアイコンが表示されとる。。
えー、
ということで、Powershellでzipファイル作る方法を検索。
Compress-Archive -Path <ファイルパス> -DestinationPath <出力先.zip>
でzipし、Lambdaにアップロードする。
アップロードできた。
が、、、
ファイル名の前にzipファイル名のディレクトリパスがついてしまい、
ツリー構造が表現できていませんでした。
ぴーんち!
誰にも質問できないし、
かなり挫折しそうになる。。
しかし、私は「非エンジニア」という最強バッチを持っている
「できなくて当たり前」「できなくても恥ずかしくない」
みんな優しいはず!
ということで、
「teratail」というプログラマに特化したQAサイトで質問してみました
https://teratail.com/questions/162184
suzu6様ありがとうございます!!!!
7zipを使って圧縮したところ、無事Lambdaへのアップロードができ、
ツリー構造で表示されました。
そしてAWSドキュメントをきちんと読まなかったことに反省。
Lambdaにアップロードするzipは、7zipで圧縮しなくてはいけないらしく
さらに、直下ディレクトリを選択し、そのうえで圧縮する。
(Lhaplusじゃだめだったよ)
##いよいよAWS Lambdaで実践
んでもって、ようやく、関数ファイルを実行モジュール付きでアップロード完了。
無事WEB画面で実行モジュールやPythonファイルが、
ツリー構造で表示されています。
そして、テストイベントの設定。
なんだかよくわかんないけど、
イベントテンプレートの「Hello world」にイベント名を付けて
「作成」とするのだけでOKでした。
(テストイベントについては、
なにかサイトを参考にさせていただいていたのですが、
どの記事を閲覧していたか、検索履歴がなくなってしまいました。
ごめんなさい。)
結果・・・・
実行結果が「null」っていうのが気になるけど。。
Twitterにも投稿されていました。
(テストだから内部の仮想処理だけで終わるのかと思ったら、違った)
##トリガーの設定
ということで
トリガーにCloudWatch Eventsを設定して、
cronでトリガー設定。
毎時45分にハンドラーが動く設定をしておく。
45分までそわそわ待つ。
。。。45分!
そして、
Twitterを確認してみる。。。
と、投稿されているーーーーー!!
歓喜!(^^)/
メモ:
このローストビーフ、実はランキング3位のメニューです。
なんで、1位と2位じゃないの?って話なのですが、
理由としては、Twitter社の規約上一定期間内の同様の内容の連続投稿はNGになっている?ためです。(たぶん)
テストでランキング1位と2位はつぶやいてしまったため、
自動投稿しようとすると403エラーが返されてしまいました。
なので3位メニューをLambdaに設定しています。
##まとめ
zipの方法という、どうでも良いことに結構時間をさかれてしまったのですが、
(zipの方法ってさ、
みなさん当たり前のようにLINUX環境でやっているんですよね。
Windowsローカルのファイルやディレクトリをzipにするための参考記事がみつかりませんでした。。<というか当たり前すぎて、皆さん書かないのかも>)
無事4つの目的達成できました。
今回のテーマを選んだ理由
①以前からAPIで何かするってことをしたかった。
②現在勉強中のPythonでなんか作ってみたかった。
③Lambdaを使って何かできないかな~、サーバレスかっちょいいと思った。
④今晩作るおすすめレシピをゲットできたら良いな~と思った
このソースのままだと、ランキングを取得しているといえど、
楽天レシピ側が更新されるまで、
ほぼ毎回同じレシピをつぶやかれてしまうので、
トリガーは無効化にしてしまいました。
なので、定期的につぶやくようなbot化はできていないけど。。
(なんとなくrandomモジュールインストールして、random.randint(1,4)とかをランキングの整数に変数指定とかで、
もう少しランダムなメニューを配信できるようになるのでは?と思っている)
一応目的達成できて良かった!!
##最後に
この記事群を書くにあたって
- インターネットの力は絶大、それなりにやりたいことできた
- 改めて自分のモチベーションの上げ方を認識できた(記事には書いてないけど)
のは良い収穫でした。
改めまして、
学習の参考にさせていただいてる記事の著者さんありがとうございます。
質問にご回答くださりありがとうございます。
本記事についての修正やもっとコードはこうしたら良いよ、などがありましたら、
引き続きコメントをお待ちしています。