5
8

More than 3 years have passed since last update.

【Python】LINE BOTに天気予報を答えさせてみた

Last updated at Posted at 2020-09-12

はじめに

tenki.jpをスクレイピングして天気予報をlinebotに組み込んでみました。
https://tenki.jp/

*linedeveloperは登録されている前提でお話します!

環境

windows
python 3.6.4

先に完成図

IMG_3332.jpg

まずはスクレイピング準備

    #対象のサイトURL
    url = "https://tenki.jp/forecast/6/30/6200/27100/"
    #インスタンス作成
    res = urllib.request.urlopen(url)
    soup = BeautifulSoup(res, 'html.parser')

'html.parser'はスクレイピングに必要なフィルターみたいなもの。

classごとのスクレイピング

weather = soup.find_all("p", class_="weather-telop")
    temp = soup.find_all("dd", class_="high-temp temp")
    low_temp = soup.find_all("dd", class_="low-temp temp")
    tds = soup.select("tr.rain-probability td")
    hini = soup.find_all("h3", class_="left-style")

上から、「天気、気温、最低気温、降水確率、日にち」の順番でスクレイピングしています。
find_allやselectメソッドの使い分けはもっと慣れる必要があるが、selectだけ使っとけば問題なさそうだと思った。

出力に備えて

    tenki = hini[0].getText() + "\n\n" + weather[0].getText()
    kion = "\n最高 " + temp[0].getText()
    low_kion = "  最低 " + low_temp[0].getText()
    rain1 = "\n\n降水確率\n00-06時  " + tds[0].getText()
    rain2 = "\n06-12時  " + tds[1].getText()
    rain3 = "\n12-18時  " + tds[2].getText()
    rain4 = "\n18-24時  " + tds[3].getText()

先ほどスクレイピングした物は全部リストとなって取得される。
今回は基本的に[0]の中身が今日のデータで、[1]の中身が明日のデータだったため割とあっさり出来た。

スクレイピングファイル(scw.py)の全体図

scw.py
import urllib.request
from bs4 import BeautifulSoup

def getw():    #今日の天気スクレイピング
    #対象のサイトURL
    url = "https://tenki.jp/forecast/6/30/6200/27100/"
    #インスタンス作成
    res = urllib.request.urlopen(url)
    soup = BeautifulSoup(res, 'html.parser')
    #対象の要素
    weather = soup.find_all("p", class_="weather-telop")
    temp = soup.find_all("dd", class_="high-temp temp")
    low_temp = soup.find_all("dd", class_="low-temp temp")
    tds = soup.select("tr.rain-probability td")
    hini = soup.find_all("h3", class_="left-style")


    tenki = hini[0].getText() + "\n\n" + weather[0].getText()
    kion = "\n最高 " + temp[0].getText()
    low_kion = "  最低 " + low_temp[0].getText()
    rain1 = "\n\n降水確率\n00-06時  " + tds[0].getText()
    rain2 = "\n06-12時  " + tds[1].getText()
    rain3 = "\n12-18時  " + tds[2].getText()
    rain4 = "\n18-24時  " + tds[3].getText()


    a = tenki+kion+low_kion+rain1+rain2+rain3+rain4
    return a

def tom_getw():    #明日の天気スクレイピング
    #対象のサイトURL
    url = "https://tenki.jp/forecast/6/30/6200/27210/"
    #インスタンス作成
    res = urllib.request.urlopen(url)
    soup = BeautifulSoup(res, 'html.parser')
    #対象の要素
    weather = soup.find_all("p", class_="weather-telop")
    temp = soup.find_all("dd", class_="high-temp temp")
    low_temp = soup.find_all("dd", class_="low-temp temp")
    tds = soup.select("tr.rain-probability td")
    hini = soup.find_all("h3", class_="left-style")

    tenki = hini[1].getText() + "\n\n" + weather[1].getText()
    kion = "\n最高 " + temp[1].getText()
    low_kion = "  最低 " + low_temp[1].getText()
    rain1 = "\n\n降水確率\n00-06時  " + tds[4].getText()
    rain2 = "\n06-12時  " + tds[5].getText()
    rain3 = "\n12-18時  " + tds[6].getText()
    rain4 = "\n18-24時  " + tds[7].getText()

    b = tenki+kion+low_kion+rain1+rain2+rain3+rain4
    return b

あとはこの関数をlinebotのmain.pyに読み込ませる。
main.pyの全体図*こちらの記事を参考にしました。

main.pyの全体図

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
import urllib.request
from bs4 import BeautifulSoup


import scw    #先ほどファイルをインポート

app=Flask(__name__)
#環境変数の取得
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 "cheer up!!2"

@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):
    #入力された文字を取得
    text_in = event.message.text

    if "今日" in text_in:   #scw.pyのgetw関数を呼び出している
        line_bot_api.reply_message(event.reply_token,TextSendMessage(text=scw.getw()))
    elif "明日" in text_in:   #scw.pyのtom_getw関数を呼び出している
        line_bot_api.reply_message(event.reply_token,TextSendMessage(text=scw.tom_getw()))
    else:   #「今日」「明日」以外の文字はオウム返しする
     line_bot_api.reply_message(event.reply_token,TextSendMessage(text=event.message.text))


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

ユーザーが「今日」という文字が含まれている文字を入力すると、今日の天気が出るようにした。
あとはデプロイして完成!
IMG_3332.jpg

最後に

もっとスマートに書けるはずなので、次へ課題にしておく。
あと、全然面白みがないBOTなので、雨だったら「傘もった?」などの通知が来るなどのアレンジを加えるなど、やれる事はいっぱいあるので此方も次の課題にしておこう。

全く関係ない話だが、腰が痛い。

5
8
3

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
8