根尾くん、プロ初ヒットおめでとう!
— ゆーさん (@fukannk0423) August 11, 2020
プログラムも無事に動いてくれました
NEO-METER 1 pic.twitter.com/tl05IWZVIm
2018年ドラフト会議で4球団競合の末中日ドラゴンズに入団した根尾昂選手ですが、2019年の間はなかなか1軍での出番をもらえずノーヒットでシーズンを終えました。
しかし2020年は2軍での打撃成績の向上にともなって1軍に呼ばれる機会が増え、プロ初ヒットを待ちわびるファンが根尾くんの打席に注目するようになりました。
僕もそんなファンの一人です。ということで今回は、イチメーター(ICHI-METER)になぞらえて根尾くんのプロ初ヒットの瞬間を記録するためのプログラムをPythonで書きました。
よかったこと
根尾くんの初ヒットまでにプログラムを完成させないといけないという制限がある中なんとか動くプログラムの作成までこぎつけることができた
悪かったこと
プログラムの中身に関してはまだまだ納得いかない要素が多く、「動きゃなんでもいい」というような付け焼刃なプログラムになってしまった
ということで、ここで振り返りたいと思います。
NEO-METER.pyの内容
基本的には、
1分ごとにスポナビの試合速報ページから根尾くんの安打数をスクレイピングするループを回して、安打数が1になったらbreakし「プロ初ヒット」のメッセージを出す
という内容のプログラムです。
単純にそれだけだと根尾くんのヒットが出るまで何日でもループを続けてしまうので、ループを抜けるための条件をいくつか追加しています。
- 試合が行われてない時(試合終了時)
- 根尾くんが試合に出てない時
- 240回ループを回した時
以下がスクリプトです。
import requests
import time
from bs4 import BeautifulSoup
import re
import pandas as pd #今回はデータ処理とかしてないので使ってない
neo_meter = 0 #根尾くんの安打数
count = 0 #ループした回数
endgame = False #試合終了を判断
#1分ごとにwhileループを回す
while neo_meter == 0:
#試合終了を判断するためにスポナビの試合ページをスクレイピングする
html_eg = requests.get('https://baseball.yahoo.co.jp/npb/game/2020081102/top')
soup_eg = BeautifulSoup(html_eg.content, "html.parser")
ext_eg = soup_eg.select(".bb-gameCard__state")
ext_eg_2 = ext_eg[0].text
if '試合終了' in ext_eg_2:
print('試合は終了しました')
endgame = True
break
print('試合継続中')
#ループを240回回したらbreakする
if count >= 240:break
#スポナビの試合ページから選手の試合成績をスクレイピングする
html = requests.get('https://baseball.yahoo.co.jp/npb/game/2020081102/stats')
soup = BeautifulSoup(html.content, "html.parser")
ext = soup.select("td")
txt = []
for i in ext:
txt_temp = i.text
txt.append(re.sub('\n', '', txt_temp))
#根尾くんの試合成績の部分を抜き出し、試合に出場してなかったらbreakする
kensaku = '根尾'
ind = []
for i,name in enumerate(txt):
if kensaku in name:
ind.append(i)
if len(ind) == 0 :break
neo = txt[ind[0]-1:ind[0]+22]
'''
スポナビのページのHTMLの仕様で、
ビジターチームの打席の結果だけ、</td>が省略されているので成績表示がバグる。
NEO-METERには直接影響しないので今回はスルー
'''
#根尾くんの安打数を確認しprintする
#安打数が0だったらもう一度ループ、0でなかったらbreakする
neo_meter = int(neo[5])
count = count + 1
print('NEO-METER', neo_meter)
if neo_meter != 0:break
print('終了まであと', 240 - count, '回ループを回します')
time.sleep(60)
#breakの条件によってメッセージを出す
if neo_meter > 0:
print('根尾選手、プロ初ヒット!\nN E O - M E T E R ', neo_meter-1, '→', neo_meter)
else:
if len(ind) == 0:
print('根尾くんは今日はまだ試合に出てないみたい')
elif endgame == True:
print('根尾くんプロ初ヒットならず\nまた次の試合')
elif count >= 240:
print('240回ループを回したのでプログラムを終了します')
else:
print('予期せぬエラーが起きました。')
exit()
反省点
- ところどころバグを起こす要素が残っている
-
ind[]
のリストの要素が2つ以上になった場合うまく成績を抜き出せない可能性 - その他、主に制御文関連に自信なし
-
- 最初に日付を
input()
で入力することでその日の中日の試合のページをスクレイピングするという機能にしたかった- というか今日の日付から勝手にサイトをクローリングして中日の試合に飛ぶようにしたかった
- というか今日の日付自体自動で取得できる気がする
- というか今日の日付から勝手にサイトをクローリングして中日の試合に飛ぶようにしたかった
- 「只今根尾くんは打席に立っています どきどき」とか「現在相手チームの攻撃 根尾くんはセンターの守備位置についています」とかもっと状態を逐一報告させたかった
- 根尾くんがヒットを打った日を同時に表示しておいた方がのちのち振り返るときに記念日の感があってよかった
- 厳密には今日の試合の安打数のカウントをしているだけなので、ICHI-METERのように通算安打をカウントする際は改変が必要
- ループを抜けたい時にいつでも抜けられる機能を追加したかった
- プログラムが流れ作業っぽすぎてまとまりがない
- オブジェクト指向っぽいプログラムを作成できなかった
と反省する部分はたくさんありますが、とりあえず根尾くんの記念すべきプロ初ヒットを自分なりに祝うことができたので嬉しいです。今後も野球関連でおもしろそうなプログラムを書いていきたいです。
展望
「任意の選手の通算安打数をカウントする」という内容でclass化して「XXX-METER」というモジュールを作る