目的
工学系のくせに外には出るのでいつも服装を考えるのですが、天気予報をチェックしない人間なのでよく失敗をします。
そこで、LINE botちゃんに天気(気温)を教えていただこうと思います。
まずはオウム返しで構築とテストしてから本番のコーディングを行うことをおすすめします。
参考
この記事は作業記録&備忘録みたいなやつです。詳しい・分かりやすいものを読みたい方は以下のリンクへどうぞ。
Python + HerokuでLINE BOTを作ってみた
PythonでLINEBotはじめました(冷やし中華的な)【前編】
PythonでLINEBotはじめました(冷やし中華的な)【後編】
LINE Developersに登録
まずLINE Developersに登録します。登録は簡単です。
https://developers.line.me/ja/
プロバイダー&チャネルの作成
LINE Developersに登録したらプロバイダーを作成します。英語の場合右下で言語を切り替えて下さい。
プロバイダーの中にチャネル(アプリ)を作成します。
画面が続いてて分かりにくいいかと思いますが
- プロバイダー作成を押す
- プロバイダー情報を入力(プロジェクト的な)
- チャネル情報を入力(botの名前とか)
です。すぐ終わります。
必要な情報を取得しておく
APIを利用するために
- チャネルアクセストークン
- チャネルシークレット
-
Webhook URL
の3つが必要になります。上2つはbotの管理画面から取得出来ます。別のタブにあるので探してみてください。
Webhook URLはHerokuを設定してから取得します。
Herokuの設定
一旦Herokuの設定に移ります。まずアカウントの登録をしましょう。
その後、Heroku CLIというコマンドラインインターフェースをインストールします。
Heroku CLI : https://devcenter.heroku.com/articles/heroku-cli#download-and-install
Herokuログイン
プロンプトで
$heroku login
を実行するとキー入力を促されるので何か入力して下さい。するとブラウザ経由でログイン出来ます。
Herokuアプリケーションの作成
$heroku create アプリ名
で新規アプリを作成できます。アンダーバー_
は使えないので注意です。
環境変数の設定
環境変数を設定します。ここのやり方は人それぞれらしいですが僕は参考サイトと同様に設定します。
先ほど控えた2つの文字列を設定してあげましょう。
$heroku config:set YOUR_CHANNEL_ACCESS_TOKEN="チャネルアクセストークン" --app アプリ名
$heroku config:set YOUR_CHANNEL_SECRET="チャネルシークレット" --app アプリ名
Webhookの設定
LINE Developersのコンソールに戻り、WebhookのURLを設定します。
Webhook URL:https://アプリ名.herokuapp.com/callback
更新を押し、webhookを利用するに設定で完了です。
https://github.com/line/line-bot-sdk-java/tree/master/sample-spring-boot-echo#step-2
こちらの[Deploy to Heroku]を押してそこからアプリを作るとEchoBotをデプロイできます。
コーディング
・LINE Developersでのbotの設定
・Herokuの設定
・両者の連携
が完了しました。ここからコーディングに入ります。
ライブラリのインストール
今回はflask
とline-bot-sdk
を中心に使用します。
pip install flask line-bot-sdk
僕の環境では
flask : 1.1.1
line-bot-sdk : 1.16.0
です。
加えてスクレイピング用のライブラリは以下を使用します。
soupsieve==2.0
urllib3==1.25.8
beautifulsoup4
作業ディレクトリとその構成
どこでもいいですがプロジェクト用にディレクトリを作成することをおすすめします。
構成:
line_bot(作業dir)
├ main.py
├ scrape.py
├ Procfile
├ runtime.txt
└ requirements.txt
ファイルの中身
①main.py
本体です。オウム返しでテストしたい場合はこちらを参考になると思います。
※APIキーの変数名に注意
#必用なものをインポート
from flask import Flask, request, abort
import os
import scrape as sc
from linebot import (
LineBotApi, WebhookHandler
)
from linebot.exceptions import (
InvalidSignatureError
)
#LINEでのイベントを取得
from linebot.models import (
MessageEvent, TextMessage, TextSendMessage,
)
app = Flask(__name__)
#環境変数取得
YOUR_CHANNEL_ACCESS_TOKEN = os.environ["LINE_BOT_CHANNEL_TOKEN"]
YOUR_CHANNEL_SECRET = os.environ["LINE_BOT_CHANNEL_SECRET"]
line_bot_api = LineBotApi(YOUR_CHANNEL_ACCESS_TOKEN)
handler = WebhookHandler(YOUR_CHANNEL_SECRET)
#アプリケーション本体をopenすると実行される
@app.route("/")
def hello_world():
return "hello world!"
#/callback のリンクにアクセスしたときの処理。webhook用。
@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.message.text(ユーザのメッセージ)を返信
line_bot_api.reply_message(
event.reply_token,
TextSendMessage(text=event.message.text))
'''
line_bot_api.reply_message(
event.reply_token,
TextSendMessage(text=sc.getWeather())
)
if __name__ == "__main__":
# app.run()
port = int(os.getenv("PORT"))
app.run(host="0.0.0.0", port=port)
②scrape.py
天気情報をスクレイピングします。自分で書く予定だったのですがとりあえず
こちら→https://qiita.com/RIRO/items/1b67b0418b08a52de0d6
のコードを少し改変しました。ありがとうございます。
#ライブラリのインポート
import requests
from bs4 import BeautifulSoup
def getWeather():
#tenki.jpの目的の地域のページのURL(今回は東京都調布市)
url = 'https://tenki.jp/forecast/3/16/4410/13208/'
#HTTPリクエスト
r = requests.get(url)
#プロキシ環境下の場合は以下を記述
"""
proxies = {
"http":"http://proxy.xxx.xxx.xxx:8080",
"https":"http://proxy.xxx.xxx.xxx:8080"
}
r = requests.get(url, proxies=proxies)
"""
#HTMLの解析
bsObj = BeautifulSoup(r.content, "html.parser")
#今日の天気を取得
today = bsObj.find(class_="today-weather")
weather = today.p.string
#気温情報のまとまり
temp=today.div.find(class_="date-value-wrap")
#気温の取得
temp=temp.find_all("dd")
temp_max = temp[0].span.string #最高気温
temp_max_diff=temp[1].string #最高気温の前日比
temp_min = temp[2].span.string #最低気温
temp_min_diff=temp[3].string #最低気温の前日比
#とりあえず動くのを見たいので天気と気温を繋げて返しています。
return weather+temp_max+temp_min
③Procfile
プログラムの実行方法を記載します。
web: python main.py
④runtime.txt
Pythonのバージョンを記載するテキストファイルです。
3.7.7ではエラーが出たので3.6.10にしています。Herokuが3.7未対応なのかな?
python-3.6.10
⑤ requirements.txt
インストールするライブラリを記載するテキストファイルです。
Flask==1.1.1
line-bot-sdk==1.16.0
soupsieve==2.0
urllib3==1.25.8
beautifulsoup4
天気情報をスクレイピングするのでscrape.py
があります。EchoBot(オウム返し)などは他4つで大丈夫です。
Herokuにデプロイする
※gitをインストールしてない人はインストールしましょう
// gitの初期ファイルを作成
git init
// ローカルリポジトリに結びつくリモートリポジトリを設定
heroku git:remote -a (自分で決めたアプリ名)
// 変更したファイルを全てインデックスに登録
git add .
// 変更したファイルをリポジトリに書き込む("inital commit"はコメントなのでなんでも良い)
git commit -m "inital commit"
// herokuにローカルで作成したファイルをpush
git push heroku master
※僕はここでエラーが出ました
ここでrequirements.txt
のbeautifulsoup4
のスペルをミスっててエラーが出ました。
僕はバージョン指定が悪いと思いバージョンを変えてtryしたのですが、ライブラリ名がミスってました()
Heroku側で確認しておく
Herokuのダッシュボードでactivityの確認をしましょう。画像のようになっていれば成功です。
webhook検証のエラー
この部分はサンプルをコピーして利用したのですが
ボットサーバーから200以外のHTTPステータスコードが返されました
というエラーが発生します。
が、BOTは正常に動くようなので無視しました。
動作確認
BOT管理画面にあるQRで友達追加して、何かメッセージを送ってみましょう。
天気の返信(orオウム返し)が成功したら成功です。
Next
現在は天気と気温を文字列で送っているだけなので
- フォーマットを整える
- 設定の追加(Regionや定期送信)
- Flex Messageの挑戦
などをできればと思います。他プロジェクトや勉強もあるのでゆっくり更新します。
参考記事の方々ありがとうございました。