LINE+Python+天気API を活用してチャットボットを作成してみた

#はじめに
趣味でプログラミングを勉強しているのですが、ふと「チャットボット作れたら面白いんじゃね？」と思い、今更ながら開発してみようと挑戦をしました。
苦戦しつつも"圧倒的コピペ"により、とりあえず動くものが出来たので投稿をします。
※Qiitaは初めての投稿になるので、あたたか〜く読んでもらえると幸いです。
※また前提として私はエンジニアでは無いため、見当違いの事を書いていたらご指摘をお願いいたします･･･

#自己紹介
・社会人3年目
・事業会社でマーケティングに従事
・学生時代は理系でJavaを少し経験
・趣味でプログラミングを長く浅く続けている
・GitHubアカウント：https://github.com/neonsk

#作ったもの
LINE上にて、入力に対してオウム返しをし、「天気」と入力した時だけ天気の情報を返してくれるBotを開発しました。天気の情報はlivedoorの天気APIを活用しています。
![line_screenshot.png](https://qiita-image-store.s3.amazonaws.com/0/310010/cb94be89-14c9-a0ac-490f-f867678d12f9.png)



#手順
##1.LINE Developers アカウントの作成
こちらのURLから簡単にアカウントを作成することが出来ます。というより既存のLINEアカウントでログインをするイメージです。
https://developers.line.biz/ja/?status=success

LINE Developersのアカウントを作成後ログインし、プロバイダー、新規チャネルの作成を行うと、下記のような管理画面が表示されます。ここに記載されている「Channel Secret」、「アクセストークン」を後ほどのpythonファイルに転記し、「Webhook URL」は後ほど設定します。
![LINEDevelopers.png](https://qiita-image-store.s3.amazonaws.com/0/310010/1cd6d5f3-1dfd-e299-f555-ee35c99bd5cf.png)


##2.Herokuアカウントの作成
LINEのチャットボットではHerokuを活用している事例が圧倒的に多かったので、こちらを活用します。
Herokuとは簡単にいうと「アプリを実行するためのプラットフォーム」です。無料で活用でき、Gitにてpushすることで、pythonなどのファイルをアップロードできます。
（Herokuの詳しい内容はこちらが分かり易かったです。https://www.sejuku.net/blog/7858）

まずはHerokuにてアカウントを作成し、HerokuCLIをダウンロードしコマンドラインにてHerokuを実行できるようにします。
https://id.heroku.com/login

その後、コマンドラインよりログイン、アプリの登録、環境変数の設定、を行います。
LINEDevelopersの管理画面を確認し、文字列Aには「Chanel Secret」の文字列を、文字列Bには「アクセストークン」を発行し、発行された文字列を入力します。
※herokuに「linechabot-sk」というアプリ名を登録する場合の記載

```
$ heroku login
（自身のログインID・PASS入力）

$ heroku create linechatbot-sk

$ heroku config:set YOUR_CHANNEL_SECRET="文字列A" --app linechabot-sk
$ heroku config:set YOUR_CHANNEL_ACCESS_TOKEN="文字列B" --app linechabot-sk
```

##3.実装
Googleで「line chatbot python」と検索すると多くの方のソースコードが出てくるので、完全にそちらを引用しました。また直近APIで天気情報の取得を学習したので、そのAPIもソースに組み込みました。

```python:main.py

from flask import Flask,request,abort
from linebot import LineBotApi,WebhookHandler
from linebot.exceptions import InvalidSignatureError
from linebot.models import MessageEvent,TextMessage,TextSendMessage
import os
import requests
import pprint

app=Flask(__name__)
#環境変数の取得
YOUR_CHANNEL_ACCESS_TOKEN="文字列B"
YOUR_CHANNEL_SECRET="文字列A"
line_bot_api=LineBotApi(YOUR_CHANNEL_ACCESS_TOKEN)
handler=WebhookHandler(YOUR_CHANNEL_SECRET)

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

    body=request.get_data(as_text=True)
    app.logger.info("Request body"+body)

    try:
        handler.handle(body,signature)
    except InvalidSignatureError:
        abort(400)
    return "OK"

@handler.add(MessageEvent,message=TextMessage)
def handle_message(event):
    #入力された文字列を格納
    push_text = event.message.text

    #リプライする文字列
    if push_text == "天気":
        url = 'http://weather.livedoor.com/forecast/webservice/json/v1?city=130010'
        api_data = requests.get(url).json()
        for weather in api_data['forecasts']:
            weather_date = weather['dateLabel']
            weather_forecasts = weather['telop']
            print(weather_date + ':' + weather_forecasts)
        reply_text = api_data["description"]["text"]
    else:
        reply_text = push_text

    #リプライ部分の記述
    line_bot_api.reply_message(event.reply_token,TextSendMessage(text=reply_text))

if __name__=="__main__":
    port=int(os.getenv("PORT",5000))
    app.run(host="0.0.0.0",port=port)
```

ちなみに下記の部分がBotとして返す値となるので、「reply_text」に代入する文字列を変更すれば、様々な返答をすることができるようになります。今回の場合はLINE上で入力された文字列が「天気」の場合のみif文により天気の情報を取得し、「reply_text」に代入をするようにしています。

```python

#リプライ部分の記述
    line_bot_api.reply_message(event.reply_token,TextSendMessage(text=reply_text))
```

その他、下記ファイルをそれぞれ作成しました。

```:runtime.txt(pythonのバージョンを記載)
python-3.6.0
```

```:requirements.txt
Flask==0.12
line-bot-sdk
```

```:Procfile(pythonのファイル名は各自が設定をしたファイル名を記載)
web: python main.py
```

ちなみに上記4つのファイルは同一ディレクトリに格納しておきます。
私の場合は下記のようなディレクトリに格納しております。

```
Desktop/linechatbot/
 →main.py
 →Procfile
 →requirements.txt
 →runtime.txt
```

##4.ファイルのデプロイ
Herokuのアプリからソースコードをローカルにコピーし、デプロイできるようにします。

```
$ heroku login
$ heroku git:clone -a linechatbot-sk
```

コマンドよりデプロイ出来る状態か確認します。

```
$ git remote -v
heroku	https://git.heroku.com/linechatbot-sk.git (fetch)
heroku	https://git.heroku.com/linechatbot-sk.git (push)
```

実装にて作成した4つのファイルをHerokuにデプロイします。

```
$ git init
$ git add .
$ git commit -m "任意の文字列"
$ git push heroku master
```

##5.Webhookの設定
LINE上に投稿された文字列を飛ばす先のURLの設定を行います。
LINE　Developersの管理画面にて下記設定を行います。
・Webhook送信　：　利用する
・Webhook URL　：　https://linechatbot-sk.herokuapp.com/callback


以上で設定、実装は終了となります！
スマホでLINEを友達登録し、何らかの投稿を行うと返答をしてくれると思います。

#所感・学んだこと
-簡単にチャットボットを作ることができ、純粋に感動した
-git、Herokuの使い方を何となく覚えた
-上手く繋がらない時のエラーと戦う忍耐力が付いた

#詰まったポイント
###LINE Developers のWebhookURLにて接続エラーが発生する
接続確認を行うと赤字でエラーが発生しており、解消しようとひたすら戦っていたのですが、結論解消しなくても接続ができました。理由は良くわからないのですが、時間を消費してしまいました。。
![webhook_error.png](https://qiita-image-store.s3.amazonaws.com/0/310010/61b48fd4-f4b3-da72-1a82-68543a1b2dd5.png)


###LINEからの応答が無い
LINEに投稿をしても全く返答が無い状態が続いておりました。
原因はgitに別途レポジトリを作成しており、そこにひたすらpushをし、繋ごうとしていました。
冷静に考えてみれば、Herokuにpushをしていないため、LINE側からすると「https://git.heroku.com/linechatbot-sk.git に飛ばせって記入したくせに、そんなファイルねーじゃねえか！」ってなる話でした。
しっかり下記を実行する事で解決しました。（数時間費やしてしまったなあ。。）

```
$ heroku login
$ heroku git:clone -a linechatbot-sk
$ git remote -v
heroku	https://git.heroku.com/linechatbot-sk.git (fetch)
heroku	https://git.heroku.com/linechatbot-sk.git (push)
```

#今後やりたい事
・（出来るのであれば）AlexaとLINEチャットボットを連携させ、LINE上からAlexaに指示を出す
・チャットボットと他のAPIを連携させ、何か面白そうなボットを作る

#参考
下記を見ながら色々調べ実装することができました。ありがとうございました！

・Git の基礎勉強 〜Git によるバージョン管理を使う〜
https://tracpath.com/bootcamp/learning_git_firststep.html
・PythonでLine botを作ってみた
https://qiita.com/krocks96/items/67f7510b36945eb9689b