PythonでLINEBotはじめました(冷やし中華的な)【前編】

PythonでLINEBotはじめました(冷やし中華的な)【前編】

ずっと前からハッカソンでLINEbotとか使いたかったけど、手をだせなかったので今更ながらはじめましたあくまでも簡単な練習としてEcho的なBotを作成しています。今回はHerokuへデプロイをするつもりでしたが、ボリュームが多くなってしまったので前後編としました。 今回のエントリーは前編として、ローカル環境でのbot作成までを行ってみています。

今回はpythonとFlaskを使ってbotを作成しています。

今回のエントリーでは以下の2つを参考させていただいています。本当にありがとうございます。

【参考1】

qiita.com

【参考2】

qiita.com

Botを作成する。

まずはLINEのデベロッパーコンソールにログインしてBotの基本部分を作成していきます。

最初にLINE developersにアクセスするところからスタートです。アクセスすると以下の様な画面になります。

f:id:ueponx:20180614063810p:plain

画面中の【MessagingAPI(ボット)をはじめる】ボタンをクリックします。

f:id:ueponx:20180614065108p:plain

ログインを促されます。(すでにログインしている場合には出ないかもしれません)開発しようと考えている人がユーザー登録してないとは思いにくいのでこの部分の手順に関しては省略しますがこのあたりを参考してもらえればいいのかなと思います。

f:id:ueponx:20180614064929p:plain

ユーザ登録をしている人はそのまま【ログイン】ボタンをクリックしてください。

続いては画面左の【新規プロバイダー】を作成します。すでに実験などをしている場合にはプロバイダーやチャンネルが作成されていると思いますが、今回はそれとは別でそれらを作成していきます。(全くの新規の場合は少し画面が違うかもしれません)

f:id:ueponx:20180614070600p:plain

ログイン後このような画面に遷移すると思いますので画面の左側の【新規プロバイダー作成】のボタンをクリックします。すると以下のような画面になります。

f:id:ueponx:20180614071123p:plain

新規プロバイダーの名前の登録になります。わかりやすいものがいいとは思いますので、今回は【Mashup名古屋】というプロバイダーを作成してみることにしました。入力が終わったら確認ボタンをクリックします。

f:id:ueponx:20180614071336p:plain

クリックすると確認画面が表示されますので、間違いなければ再度【作成ボタン】をクリックします。 f:id:ueponx:20180614071557p:plain

クリックするとプロバイダーが作成されプロバイダー一覧にも表示されるようになります。

f:id:ueponx:20180614072025p:plain

プロバイダー名の隣にある歯車のアイコンをクリックすればプロバイダーの管理画面に入れます。名前の変更や削除も可能です。

f:id:ueponx:20180614072402p:plain

では、続いて【Messaging API】ボタンをクリックします。

f:id:ueponx:20180614072510p:plain

次の処理は【新規channel作成】となります。

f:id:ueponx:20180614072611p:plain

画面全体は以下のようになっています。

f:id:ueponx:20180614073032p:plain

Messaging APIの情報を入力する項目は以下の情報となります。

  • アイコン
  • アプリ名(※アプリ名を設定した後、7日間は変更できません。
  • アプリ説明
  • プラン(【Developer Trial】と【フリー】からの選択)
  • 大業種(選択式)
  • 小業種(選択式)
  • メールアドレス

アプリ名の変更が7日間できないのでここは厳しいかも?(ぬるいブログのサンプルだったら全く問題ありませんけど) あと、プランに2つから選択になりますが、画面内の説明にある通り

Developer Trial
MessagingAPIを利用したBotを試すプランです。友だちとメッセージの送受信を行うことができます。 ※追加可能友だち数は50人に制限されています。また、Developer Trialからプランの切り替えやプレミアムIDの購入はできません。


フリー
MessagingAPIを利用したBotを開発するプランです。友だちの人数に制限はありませんが、Push messagesを利用してBotから友だちにメッセージを送信することはできません。 ※サービス拡張に向けプラン変更が可能です。

このように説明されていました。開発のテストであれば間違いなく【Developer Trial】を選択すればいいかなと思います。まあ、LINEの友達も50人もいませんけどw。

今回はこんな感じで設定してみました。入力が終わったら画面下にある【確認】ボタンをクリックします。

f:id:ueponx:20180614074940p:plain

【確認】ボタンをクリックすると情報利用に関する同意が求められるのでよく読んで問題なければ【同意】ボタンをクリックしてください。(よっぽどおかしいことは書いていないと思いますが…)

f:id:ueponx:20180614075110p:plain

【同意】ボタンのクリックで確認のダイアログが閉じて規約同意の確認画面に遷移します。

f:id:ueponx:20180614075419p:plain

あとは利用規約部分にチェックを行い【作成】ボタンをクリックします。

f:id:ueponx:20180614075603p:plain

無事にチャンネルが作成されました。

f:id:ueponx:20180614075936p:plain

ですが新しいチャンネルはまだ設定が完了していないようです。ただ、まだ入力できない情報もあるので今はまだ設定が完了していいないことだけ覚えておくことにします

f:id:ueponx:20180614080241p:plain

botソースコードの準備

今回のbot用のサンプルコードの準備をします。サンプル用のコードは公式側からGithubで公開されていますのでこれを使用します。このサンプルコードは文字列を受信して同じものを返す機能になっています。(Echo的なものです)

github.com

今回はpythonを出しましたが他にも以下のような言語があるようです。

注意点はEchoのサンプルコードのファイルはREADME.rst(ドキュメント)に入っているので単純にGit Cloneしても見当たらないので覚えておいてください。

ドキュメントにあるソースコードを貼ってろうと思ったのですがいろいろどうだろうかというところもあるので少しコードを変更しています。

【main.py】

from flask import Flask, request, abort
#環境変数取得用
import os

from linebot import (
    LineBotApi, WebhookHandler
)
from linebot.exceptions import (
    InvalidSignatureError
)
from linebot.models import (
    MessageEvent, TextMessage, TextSendMessage,
)

app = Flask(__name__)

# オリジナルの処理
# line_bot_api = LineBotApi('YOUR_CHANNEL_ACCESS_TOKEN')
# handler = WebhookHandler('YOUR_CHANNEL_SECRET')

#環境変数取得
YOUR_CHANNEL_ACCESS_TOKEN = os.environ["YOUR_CHANNEL_ACCESS_TOKEN"]
YOUR_CHANNEL_SECRET = os.environ["YOUR_CHANNEL_SECRET"]

line_bot_api = LineBotApi(YOUR_CHANNEL_ACCESS_TOKEN)
handler = WebhookHandler(YOUR_CHANNEL_SECRET)

@app.route("/")
def hello_world():
    return "hello world!"

@app.route("/callback", methods=['POST'])
def callback():
    # get X-Line-Signature header value
    signature = request.headers['X-Line-Signature']

    # get request body as text
    body = request.get_data(as_text=True)
    app.logger.info("Request body: " + body)

    # handle webhook body
    try:
        handler.handle(body, signature)
    except InvalidSignatureError:
        abort(400)

    return 'OK'


@handler.add(MessageEvent, message=TextMessage)
def handle_message(event):
    line_bot_api.reply_message(
        event.reply_token,
        TextSendMessage(text=event.message.text))


if __name__ == "__main__":
    app.run()

サンプルではFlaskrequestを使用する必要あるのがわかります。requestはHTTP関連でお馴染みのモジュールですが、Flaskウェブアプリケーション用のマイクロフレームワークになります。

Welcome | Flask (A Python Microframework)

github.com

Djangoに似たような機能を持つもののようです。PCにAnacondaをインストールしているのですがpip freezeコマンドでもインストールされていました。RaspberryPi側でも確認しましたがインストールされていました(pip,pip3ともに)。

とはいっても今回は最終的にはHerokuホスティングしてもらうのでインストールに関してはHeroku側で行う必要があります

また、コード内を眺めてみるとYOUR_CHANNEL_ACCESS_TOKENYOUR_CHANNEL_SECRETが必要になりますが、Messaging APIの設定から取得できるので後から取得します。その際もHeroku側の環境変数として設定するのが一般的のようですがさんぷるのコードでは直接代入しているではないですか! その部分をあわせるためにYOUR_CHANNEL_ACCESS_TOKENYOUR_CHANNEL_SECRET環境変数から読み込むようにコードを変更してあります。

【オリジナル】

line_bot_api = LineBotApi('YOUR_CHANNEL_ACCESS_TOKEN')
handler = WebhookHandler('YOUR_CHANNEL_SECRET')

↓ 【変更後】

#環境変数取得用
import os

…(中略)…

#環境変数取得
YOUR_CHANNEL_ACCESS_TOKEN = os.environ["YOUR_CHANNEL_ACCESS_TOKEN"]
YOUR_CHANNEL_SECRET = os.environ["YOUR_CHANNEL_SECRET"]

line_bot_api = LineBotApi(YOUR_CHANNEL_ACCESS_TOKEN)
handler = WebhookHandler(YOUR_CHANNEL_SECRET)

あと、テスト用にルートアクセスをしたときにメッセージを表示するhello_worldも追加しました。

【追加部分】

@app.route("/")
def hello_world():
    return "hello world!"

続いてはHeroku側の設定としたいところですが、とりあえずはローカル環境で実行できるかを試してみます。

アクセスに必要なCHANNEL_ACCESS_TOKENCHANNEL_SECRETの取得

デベロッパーコンソールに戻って実行に必要な``CHANNEL_ACCESS_TOKENCHANNEL_SECRET```の取得します。

f:id:ueponx:20180616061151p:plain

作成したBotの【設定が完了していません】をクリックするとChannel基本設定の画面に遷移します。

f:id:ueponx:20180616061830p:plain

画面をスクロールさせると基本情報のカテゴリの中にCHANNEL_SECRETがあるのでメモしておきます。

f:id:ueponx:20180616062418p:plain

さらに画面をスクロールさせると【メッセージ送受信設定】のカテゴリに``CHANNEL_ACCESS_TOKEN```があるので右にある【再発行】のボタンをクリックします。

f:id:ueponx:20180616062135p:plain

クリックすると以下のようなダイアログが表示されますが、初回の場合は0時間で問題ないでしょう。再度【再発行】のボタンをクリックします。

f:id:ueponx:20180616062903p:plain

以下のように表示が行われればOKです。これもメモしておきます。

f:id:ueponx:20180616063154p:plain

ローカルでテストを行う

先程の手順で実行に必要な``CHANNEL_ACCESS_TOKENCHANNEL_SECRET```の取得できたので、環境変数にセットしてローカルで実行してみます(ここではアクセスできるかになります)。

まずは、``CHANNEL_ACCESS_TOKENCHANNEL_SECRETを環境変数にセットします。以下はAnacondaPrompt(Windows10のcmd環境)でセットしています。文字は伏せています。環境変数をsetコマンド(Linuxならばexport```)でセットしています。(Macはわかりませんw)

WindowsなAnaconda環境】

(base) >set YOUR_CHANNEL_ACCESS_TOKEN=***************************************************************************************************************************************************************************************************************

(base) >set YOUR_CHANNEL_SECRET=***********************

Linuxなど】

$ export YOUR_CHANNEL_ACCESS_TOKEN=***************************************************************************************************************************************************************************************************************

$ export YOUR_CHANNEL_SECRET=***********************

あとは先程のpythonのコードを実行します。(この実行仕方では失敗してます。正解は後述しますが、それ以外の工程に関してはそのままで大丈夫です。)

【間違えた実行方法】

(base) > python main.py

【(念の為)後述する正解の実行方法-WindowsなAnaconda環境】

> set FLASK_APP=main.py
> set FLASK_DEBUG=1
> flask run --host=0.0.0.0

f:id:ueponx:20180616064724p:plain

デフォルトではポート5000番でサービスが開始されます。

実行したら、Webブラウザからアクセスしてみます。

f:id:ueponx:20180616065143p:plain

HelloWorld!が表示されました。サンプルコードに追加したHelloWorldの処理が動作したことがわかります。

続いてはこれをインターネット経由でアクセスします。ルータの設定をするのは危険なので、ここでもおなじみのngrokを使用します。

【ngrokに関しては以下を参照】

ngrok.com

使い方に関しては過去のエントリーを参照してください。エントリーではRaspberryPiで使用していますが、WindowsMacでも変わらないと思います。

uepon.hatenadiary.com

ngrokをダウンロードして任意の場所(パスの通ったところなど)にいれて以下の様に実行します。実行は別のcmdやコンソールからの実行となります。pythonプログラムとは異なるコンソールで実行してください。

> ngrok.exe http 5000

【2つのコンソールを開いての実行の様子】

f:id:ueponx:20180616070224p:plain

実行すると以下のような画面になります。その中のForwardingのところにあるアドレスがサービスが公開されたURLとなっています。

f:id:ueponx:20180616070606p:plain

それでは、このURLへブラウザからアクセスします。httpでも、httpsでもどちらでもアクセス出来ますが、今回はhttpsを使用しています。(botではhttpは使えませんのでご注意。)

f:id:ueponx:20180616070913p:plain

ではこのURLをメモっておきます。これがBotのWebhook用のURLとなります。

では、デベロッパーコンソールに移動して、今回ngrokで取得したURLを設定します。 デベロッパーコンソールの画面に戻って、作成したBotの【設定が完了していません】のあたりをクリックします。

f:id:ueponx:20180618071924p:plain

クリックすると、【Channel基本設定】画面に遷移します。

f:id:ueponx:20180618072111p:plain

画面をスクロールさせて【メッセージ送受信設定】の項目の中から

f:id:ueponx:20180618072434p:plain

【Webhook送信】の右側にある【ペン】のアイコンをクリックします。

f:id:ueponx:20180619045345p:plain

表示されたラジオボタンで【利用する】に設定をして、【更新】ボタンをクリックします。

f:id:ueponx:20180619045622p:plain

次に【Webhook URL】の右側にある【ペン】のアイコンをクリックします。

f:id:ueponx:20180618072646p:plain

すると、入力ボックスが表示されるので、ここに先程ngrokで得られたURL(httpsのもの)を入力します。画面内の注意書きにもありますが、今回はhttpは使えませんのでご注意。 また、URLの末尾に/callbackをつけるのも忘れずに!

入力値が[任意の文字列].ngrok.com/callbackとなっていれば問題ありません。

f:id:ueponx:20180618072834p:plain

入力が終わったら、更新ボタンを押して設定を完了させてください。 デベロッパーコンソールの画面に戻ると【設定が完了していません】の文字が消えています。

f:id:ueponx:20180618073616p:plain

実行してみる

実行は一度このボットと友達になる必要があります。デベロッパーコンソールから今回作成したbotのアイコンをクリックすると、【Channel基本設定】画面に遷移します。 その画面の一番下の部分に友達設定用のQRコードが表示されているので、それを使用してLINEアプリから登録を行います。

f:id:ueponx:20180618073822p:plain

QRコードで友だち追加の画面から、QRコードを読み込ませると以下のような画面になるので【追加】ボタンをタップします。

f:id:ueponx:20180619220438p:plain

無事、友だち登録が完了しました。

f:id:ueponx:20180619221110p:plain

トーク】を開くと以下のようなウエルカムメッセージが届きます。

f:id:ueponx:20180619221258p:plain

そして、いよいよ文字列を送信してみると…

f:id:ueponx:20180619221442p:plain

あれ?Echoが帰ってきていない…アクセスログをみると200(正常)が帰ってきているので問題はなさそう…コードが違う?

f:id:ueponx:20180619051428p:plain

いろいろとググったところFlaskでの実行では通常のpythonとは少し異なる実行方法が推奨されているようです。

【参照】

qiita.com

WindowsなAnaconda環境】

> set FLASK_APP=main.py
> set FLASK_DEBUG=1
> flask run --host=0.0.0.0

Linuxなど】

$ export FLASK_APP=main.py
$ export FLASK_DEBUG=1
$ flask run --host=0.0.0.0

ちなみにpythonのコードの最後の部分でapp.runの引数を以下の様に変更すると

【変更前】

if __name__ == '__main__':
    app.run()

【変更後】

if __name__ == '__main__':
    app.run(debug=False, host='0.0.0.0', port=5000)

環境変数を使用せず、そのままflask runとさせることが出来るようです。

f:id:ueponx:20180619052340p:plain

f:id:ueponx:20180619053429p:plain

あえて実験しましたが、環境変数をセットしておけば以前のようにpythonからアプリを実行しても問題はなさそうです。

(base)  >python main.py

スマートフォン側実行画面】 f:id:ueponx:20180619221835p:plain

【コンソール側実行画面】 f:id:ueponx:20180619061041p:plain

スマートフォン側の実行では、途中なんか変なメッセージがでているのですが…

ぐぐってみるとこのメッセージは自動応答系のメッセージのようです。LineデベロッパーコンソールでこれをOFFすると表示されないようですので設定をしてみます。 以下の画面から作成したアプリをクリックして

f:id:ueponx:20180619053909p:plain

【Channel基本設定】の画面に入ります。

f:id:ueponx:20180619054013p:plain

画面をスクロールさせていくと【LINE@機能の利用】の項目があると思います。 現在の設定は以下のようになっていると思います。

f:id:ueponx:20180619054222p:plain

このなかで【自動応答メッセージ】がONになっているので、毎回メッセージが表示されています。これをOFFすることにします。項目の右側にある【ペン】アイコンをクリックして

f:id:ueponx:20180619054853p:plain

ラジオボタンの「利用しない」を選択して【更新】ボタンをクリックします。

以下のようになっていればOKです。

f:id:ueponx:20180619055033p:plain

では、改めてLINEでテストで実行してみます。

f:id:ueponx:20180619222002p:plain

実行に成功しました。

おわりに

今回も長くなってしまったのでローカルでのテストができたので前半戦は終了です。今回はpythonがどうとかいうよりはFlaskの関連で躓いた感じは否めません。ただ無事に動かせてよかったかなと思います。ngrokを使用すればRaspberryPiでもBotをローカルで動かせるかなと思います。

続いてはHelokuへのデプロイをしていきたいと思います。(つづく)

/* -----codeの行番号----- */