LoginSignup
5
5

More than 3 years have passed since last update.

LINE botで天気が知りたい feat.Heroku+Python

Last updated at Posted at 2020-04-03

目的

工学系のくせに外には出るのでいつも服装を考えるのですが、天気予報をチェックしない人間なのでよく失敗をします。
そこで、LINE botちゃんに天気(気温)を教えていただこうと思います。
まずはオウム返しで構築とテストしてから本番のコーディングを行うことをおすすめします。

参考

この記事は作業記録&備忘録みたいなやつです。詳しい・分かりやすいものを読みたい方は以下のリンクへどうぞ。
Python + HerokuでLINE BOTを作ってみた
PythonでLINEBotはじめました(冷やし中華的な)【前編】
PythonでLINEBotはじめました(冷やし中華的な)【後編】

LINE Developersに登録

まずLINE Developersに登録します。登録は簡単です。
https://developers.line.me/ja/

プロバイダー&チャネルの作成

LINE Developersに登録したらプロバイダーを作成します。英語の場合右下で言語を切り替えて下さい。
プロバイダーの中にチャネル(アプリ)を作成します。
画面が続いてて分かりにくいいかと思いますが

  1. プロバイダー作成を押す
  2. プロバイダー情報を入力(プロジェクト的な)
  3. チャネル情報を入力(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の設定
・両者の連携
が完了しました。ここからコーディングに入ります。

ライブラリのインストール

今回はflaskline-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キーの変数名に注意

main.py
#必用なものをインポート
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
のコードを少し改変しました。ありがとうございます。

scrape.py
#ライブラリのインポート
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未対応なのかな?

runtime.txt
python-3.6.10

⑤ requirements.txt

インストールするライブラリを記載するテキストファイルです。

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.txtbeautifulsoup4のスペルをミスっててエラーが出ました。
僕はバージョン指定が悪いと思いバージョンを変えてtryしたのですが、ライブラリ名がミスってました()

Heroku側で確認しておく

Herokuのダッシュボードでactivityの確認をしましょう。画像のようになっていれば成功です。
b7276e159aa0cadcfe46ba23ed0d4cc4.png

webhook検証のエラー

この部分はサンプルをコピーして利用したのですが
ボットサーバーから200以外のHTTPステータスコードが返されましたというエラーが発生します。
が、BOTは正常に動くようなので無視しました。

動作確認

BOT管理画面にあるQRで友達追加して、何かメッセージを送ってみましょう。
天気の返信(orオウム返し)が成功したら成功です。

Next

現在は天気と気温を文字列で送っているだけなので

  • フォーマットを整える
  • 設定の追加(Regionや定期送信)
  • Flex Messageの挑戦

などをできればと思います。他プロジェクトや勉強もあるのでゆっくり更新します。
参考記事の方々ありがとうございました。

5
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
5