Python
python3
BeautifulSoup
Slack
slackbot

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

はじめに

日本ハムの選手がホームランを打ったときに通知してくれるslack botを作りました。
単にホームランを通知してくれるだけでは面白くないので、日本ハムの実況でお馴染みの近藤祐司さんの特徴的な実況語録で通知してもらうことにしました。

試合の情報はYahoo!JAPANのSportsNaviからスクレイピングして取得しました。
初めてスクレイピングをやったので結構雑になっているかもしれないです。

全体の概要

  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取得手順

プログラム

get_homerun_comment関数では5つのコメントの中から確率的に選んでもらうことにしました。

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の設定

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

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

実行結果

ホームランを打った時に通知してくれました。
スクリーンショット 2018-10-11 22.33.52.png

問題点

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

おわりに

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