今年のオープン戦投手成績をスクレイピングしていく!
2024年プロ野球開幕まであと少しですね。
オープン戦がおかなわれています。
本記事では、2024年のオープン戦の成績データを全球団スクレイピングする方法を紹介します。
※スクレイピングする際はサイトに負荷をかけないこと、サイトの規程等に従い行いましょう。
今回スクレイピングするサイトはこちらです。
1. インポート
使用するライブラリをインポートします。
import pandas as pd
import seaborn as sns
import time as t
import warnings
warnings.simplefilter("ignore") #警告表示を消すため
2. データの型指定用のリスト作成
スクレイピングしてくるデータの型はほぼobject型になるため、数値で扱えるように型指定をするための辞書データを作成します。
dtypes_lists_p = {
'投 手': 'object',
'登 板':'int16',
'勝 利':'int16',
'敗 北':'int16',
'セ | ブ':'int16',
'完 投':'int16',
'完 封 勝':'int16',
'無 四 球':'int16',
'勝 率':'float32',
'打 者':'int16',
'投 球 回':'float32',
'安 打':'int16',
'本 塁 打':'int16',
'四 球':'int16',
'故 意 四':'int16',
'死 球':'int16',
'三 振':'int16',
'暴 投':'int16',
'ボ | ク':'int16',
'失 点':'int16',
'自 責 点':'int16',
'防 御 率':'float32'
}
3 スクレイピングコード
メインとなるスクレイピングコード関数です。
def scraping_preseason_data_p():
start = t.time()
teams =['t','c','db','g','s','d','b','m','h','e','l','f']
body = 'https://npb.jp/bis/2024/stats/idp1op_'
tail = '.html'
#
data = pd.DataFrame()
for team in teams:
url = body + team + tail
print(url)
df = pd.read_html(url)
df2 = df[0]
df2.columns = df2.loc[1]
df2 = df2.iloc[2:,1:]
df2['投 球 回'] = df2['投 球 回'].str.replace('+','0')
df2['防 御 率'] = df2['防 御 率'].str.replace('----','0')
df2 = df2.astype(dtypes_lists_p)
df2['球 団'] = team
data = pd.concat([data,df2],axis=0)
t.sleep(1)
data.to_csv('preseason_data.csv',index=False)
print('{:.3f} [sec]'.format(t.time()-start))
startはt.time()で処理時間計測用の時刻を取得します。
start = t.time()
teamsにはURLの球団を識別する部分の文字列をリストで持ちます。
teams =['t','c','db','g','s','d','b','m','h','e','l','f']
bodyにはURLの文字列が変わらない部分の前半部です。
body = 'https://npb.jp/bis/2024/stats/idp1op_'
tailはURLの末尾となる.htmlの文字列です。
tail = '.html'
dataにpd.DataFrame()で空のデータフレームを代入します。
data = pd.DataFrame()
for文を用いて各球団のページのurlを作って、スクレイピングをしていきます。
url変数にbody、team、tailの文字列連結をすることでアクセスするURLを代入します。
printでurl変数に代入した文字列を確認のため出力しています。
for team in teams:
url = body + team + tail
print(url)
pd.read_html(url)でアクセス先のデータを取得します。
df = pd.read_html(url)
df[0]にオープン戦成績データが入っているので、df2に代入します。
df2 = df[0]
df2.columns = df2.loc[1]でカラムの名称を指定します。
df2.columns = df2.loc[1]
必要なデータの領域だけ取得するため、df2.iloc[2:,1:]をdf2に代入します。
df2.columns = df2.loc[1]
df2['投 球 回'].str.replace('+','0')でデータにある+を0に変換します。
df2['投 球 回'] = df2['投 球 回'].str.replace('+','0')
同様にdf2['防 御 率'].str.replaceで'----'を'0'に変換します。
df2['防 御 率'] = df2['防 御 率'].str.replace('----','0')
df2.astypeで2.データの型指定用のリスト作成で作成した辞書データを使い、型指定を行います。
df2 = df2.astype(dtypes_lists_p)
df2['球 団']球団がわかるようにteamの文字列を代入しておきます。
df2['球 団'] = team
dataにpd.concatで加工したデータフレームを連結していきます。
data = pd.concat([data,df2],axis=0)
高速に処理するとアクセスを短時間に高頻度することになるので、sleepで処理を1秒止めます。
t.sleep(1)
12球団分ループした後、data.to_csv()でデータを保存して最後に処理時間を出力して終了です。
data.to_csv('preseason_data.csv',index=False)
処理時間計測は最初にstartに代入していた時刻データと再度取得したt.time()の値を引けば処理時間がもとまります。
print('{:.3f} [sec]'.format(t.time()-start))とすれば、計算して出力する処理になります。
print('{:.3f} [sec]'.format(t.time()-start))
4 main関数
あとは実行するだけです。w
scraping_preseason_data_p()を呼び出せばスクレイピングが実行されます。
訳15秒で処理が終わります。
if __name__ == "__main__":
scraping_preseason_data_p()
まとめ
今年のプロ野球オープン戦の成績データを12球団分スクレイピングしてデータ取得しました。
今回は一括してcsvデータにしましたが、1球団ずつファイルを作るようにプログラムを改良したりなど自分の使いやすいようにコードを改良すると良いでしょう。
ノートブックファイルをダウンロードできます。(有料)
本記事のコードを記述したノードブックファイルを以下からダウンロードすることができます。
jupyter notebook環境で動かすことができます。
よろしければサポートをよろしくお願いします。サポートいただいた資金は活動費に使わせていただきます。