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

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

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

#環境
windows
python 3.6.4

#先に完成図
![IMG_3332.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/705524/f747663e-a469-fc38-cc87-f42358bf693c.jpeg)

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

```
    #対象のサイト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)の全体図
```python: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の全体図＊[こちら](https://qiita.com/shimajiri/items/cf7ccf69d184fdb2fb26)の記事を参考にしました。
#main.pyの全体図

```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
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](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/705524/b4a564be-b949-e847-aa21-233f8fbad086.jpeg)


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

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