Python に川の様子を見に行ってもらった件


どうも。

今回は、Slack のチャンネルで問い合わせると川の様子を伝えてくれるbotを作成した記録です。

1.やりたいこと

やりたいことはシンプルです。
川が氾濫しないか確認したいんですが、自分で行くのは危険なので、河川事務所のサイトからスクレイピングして slack 上に投稿する仕組みを作ります。

そのサイトを普通に見に行ったらいいと思うじゃないですか、
そうなんですよね・・・

台風でみんながアクセスしてて重かったんで、ということにしましょう。

2.やること

・Slackbot の作成
・スクレイピングの作成
・クラウドへのデプロイ

はい、こんだけです。

3.Slackbot の作成

slack のボットを作成します。

こちらの記事を参考にしています。
PythonのslackbotライブラリでSlackボットを作る

Slackbot の GitHub ページに行ったらそれはそれでいろいろ参考になるなることも書いてます。

slackbot         # プログラムをまとめるディレクトリ。名前はなんでも良い
├─ run.py        # このプログラムを実行することで、ボットを起動する
├─ slackbot_settings.py   # botに関する設定を書くファイル
└─ plugins                # botの機能はこのディレクトリに追加する
   ├─ my_mention.py       # 機能を書くファイル。任意の名前で良い
   ├─ __init__.py         # モジュールを示すためのファイル。空で良い
   └─ picture             # 画像を保存するディレクトリ
        └─ edogawa.jpg    # 川の画像

画像を保存するディレクトリと画像ファイルを追加しています。
bot は仕事をするたびに画像を最新の川の画像に更新して Slack に投稿します。

⇒今後の目論見をしてはこういう感じで時系列でたくさんの定点画像を取得してなんかやりたい。(bot とは違う形ですね。lambda とかで定期的に動かしといて画像を溜め込むイメージです。手法と用途を考え中。)

4.スクレイピングの作成

スクレイピングはみんな大好き Beautiful Soup の出番です。

bs4.py
import requests
import re
from bs4 import BeautifulSoup

response = requests.get('http://www.ktr.mlit.go.jp/edogawa/edogawa00375.html#p_shingyoutoku')
soup = BeautifulSoup(response.text,'lxml')

imgs=soup.find_all('img',src=re.compile('^http://www.ktr.mlit.go.jp/edogawa/saigai/live/camera/img/p_shingyoutoku.jpg'))
for img in imgs:
        print(img['src'])
        r = requests.get(img['src'])
        with open(str('任意のディレクトリ')+str('edogawa')+str('.jpg'),'wb') as file:
                    file.write(r.content)

こんな感じです・・・

いまいち感はありますよね!!
なんか汚いですけど!!

5.Slackbot に組み込む

クラウドにデプロイする前にローカルで動かしました。
my_mention.py にスクレイピングを組み込んでいきます。

my_mention.py(一部)
@respond_to('江戸川')
def mention_func(message):

    response = requests.get('http://www.ktr.mlit.go.jp/edogawa/edogawa00375.html#p_shingyoutoku')
    soup = BeautifulSoup(response.text,'lxml')

    imgs=soup.find_all('img',src=re.compile('^http://www.ktr.mlit.go.jp/edogawa/saigai/live/camera/img/p_shingyoutoku.jpg'))
    for img in imgs:
            print(img['src'])
            r = requests.get(img['src'])
            with open(str('./plugins/picture/')+str('edogawa')+str('.jpg'),'wb') as file:
                    file.write(r.content)

    message.reply('画像を取得しました')  
    files = {'file': open("./plugins/picture/edogawa.jpg", 'rb')}
    param = {
        'token':TOKEN, 
        'channels':CHANNEL,
        'filename':"filename",
        'initial_comment': "initial_comment",
        'title': "title"
    }
    requests.post(url="https://slack.com/api/files.upload",params=param, files=files)

こんな感じ。
メンションを検知してから画像を返すところまでの内容です。
ここでしれっと添付のアップロードが出てきますけど、Slackbot の GitHub ページに載ってます!

TOKEN と CHANNEL は前の部分で設定しています。

動かしたら、こんな感じに画像を取ってきました。

いい具合です。
それではクラウドに構築して稼働させましょう。

6.EC2で起動する

EC2 は無料枠で使える Linux のマシンにしています。

EC2を立てたら、SSH 接続して、Python 環境を構築して、 GitHUb から clone して、

run.py を実行します。
実行時のコマンドで、 kill されないように

./run.py

ではなく

nohup ./run.py &

で実行します。
これができてなくてしばらく kill され続けました。

7.おわりに

台風があと少しと迫ってくる中での開発は普通に期限に追われるのとはまた違った追われ方で刺激的でした。
急いでパタパタ作ってしまったのでこれをきっかけにもっといいものを作っていけたらと思います。

※途中で画像編集が面倒になってサボってます。気が向いたころにまた更新かけます。

後半えらい雑ですが、出張帰りの新幹線で書いてます。これも気が向いたらちゃんと書き直しますw