ホームラン通知slackbot作ってみた

#はじめに
日本ハムの選手がホームランを打ったときに通知してくれるslack botを作りました。
単にホームランを通知してくれるだけでは面白くないので、日本ハムの実況でお馴染みの[近藤祐司](http://www.ugk-sports.com/)さんの特徴的な実況語録で通知してもらうことにしました。

試合の情報はYahoo!JAPANの[SportsNavi](https://baseball.yahoo.co.jp/npb/)からスクレイピングして取得しました。
初めてスクレイピングをやったので結構雑になっているかもしれないです。


#全体の概要
1. 1日1回cronでプログラムを起動し、日本ハムの試合開始時間を取得する。
2. Pythonのschedライブラリを用いて試合開始時間にgone_bot関数を実行するようにスケジュールを設定する。
3. 試合時間になったらgone_bot関数を実行し、30秒に1回試合情報を取得して日本ハムの選手がホームランを打ったときに通知をする。
4. 試合が終了したときにプログラムを終了させる。

#ライブラリのインストール
```
pip install beautifulsoup
pip install slackweb
```

# SlackのWebhook URLを取得する
プログラムからslackに通知を送るためにWebhook URLを取得します。
取得手順は以下を参考にしました。

[SlackのWebhook URL取得手順](https://qiita.com/vmmhypervisor/items/18c99624a84df8b31008)

#プログラム
`get_homerun_comment`関数では５つのコメントの中から確率的に選んでもらうことにしました。

```gone_bot.py
import sched
import datetime
import time
import numpy as np
from urllib.request import urlopen
from bs4 import BeautifulSoup
import slackweb

# パーサの作成
def soup_html_parser(url):
    html = urlopen(url)
    return BeautifulSoup(html, "html.parser")

# 日本ハムの試合開始時間取得
def get_start_time(games_today):
    for game in games_today:
        if len(game.find_all('a', href='/npb/teams/8/', title='日本ハム')) != 0:
            return game.find('em').text
    return ''

# 日本ハムの試合の状況取得
def get_game_status(games_today):
    for game in games_today:
        if len(game.find_all('a', href='/npb/teams/8/', title='日本ハム')) != 0:
            return game.find('td',  colspan='2')
    return ''

# ホームランのコメントを取得
def get_homerun_comment():
    comment = ['イッツゴーンヌッ!', 'イッツ!ゴーイング!ゴーイング!ゴーンヌッ!', 'イッツアウトオブヒアッ!ゴーンヌッ!', 'シーユーレイター!', 'グッバーイ!']
    return np.random.choice(comment, p = [0.4, 0.15, 0.15, 0.15, 0.15])

def gone_bot():
    while True:
        url_date = "{0:%Y%m%d}".format(datetime.date.today())
        soup = soup_html_parser('https://baseball.yahoo.co.jp/npb/schedule/?date=' + url_date)
        games_today = soup.find_all('table', class_='teams')
        if game_today:
            status = get_game_status(game_today) 
            if status.get('class')[0] == 'active': # 試合中
                soup_game = soup_html_parser(status.a.get('href') + 'text') # 現在の回の情報を取得   
                game_F = soup_game.find_all('div', class_='item F clearfix')
                if len(game_F) != 0:
                    bat_now = game_F[0].find_all('li')[-1] # 現在のバッターの情報を取得      
                    if bat_now.find('b', class_='red') and bat_now.b.contents[-1].find('ホームラン') != -1: # 自軍の得点(ホームラン)
                        # *****にincoming webhookのurlを入力
                        slack = slackweb.Slack('*****')
                        slack.notify(text = bat_now.a.text + '!' + get_homerun_comment() + '\n' + bat_now.b.contents[-1])     
                        
            elif status.get('class')[0] == 'end': # 試合終了
                break

            time.sleep(30)


if __name__ == '__main__':   
    url_date = "{0:%Y%m%d}".format(datetime.date.today())
    soup = soup_html_parser('https://baseball.yahoo.co.jp/npb/schedule/?date=' + url_date)
    if games_today:
        start_time = get_start_time(games_today)
        if start_time != '':
            scheduler = sched.scheduler(time.time, time.sleep)
            run_at =  datetime.datetime.strptime(str(datetime.date.today()) + ' ' + start_time, '%Y-%m-%d %H:%M')
            run_at = int(time.mktime(run_at.utctimetuple()))
            scheduler.enterabs(run_at, 1, gone_bot)
            scheduler.run()
```

# cronの設定
毎日１２時にプログラムを実行するようにしました。
下記では省略していますが絶対パスで指定します。

```
0 12 * * * bash -l -c '/home/.../python /home/.../gone_bot.py &'
```

# 実行結果
ホームランを打った時に通知してくれました。
<img width="711" alt="スクリーンショット 2018-10-11 22.33.52.png" src="https://qiita-image-store.s3.amazonaws.com/0/156302/8c4996a0-50b3-ba63-2cc0-12ae752f2bd5.png">

# 問題点
現在はテキスト速報からスクレイピングしているので更新が遅いときは、スクレイピングのインターバルが30秒なので場合によっては複数回通知することがあります。

# おわりに
シーズンの試合が終わりかけているので焦って作って投稿しました。
問題点については、更新の速い一球速報などからスクレイピングすることで解決できそうなので修正したいと考えています。