プロ野球の試合の観客数データを35行のコードで取得する2023年版
はじめに
2023年もあとプロ野球は日本シリーズを残すのみになりました。
今年は関西対決で大いに盛り上がっていることでしょう。
今回は各球団のプロ野球の試合の観客数を14年分(2009年〜2022年)取得します。
データ取得元
データ取得元は、プロ野球Freakさんです。
いつもお世話になっています。!
スクレイピングコード全体
コードの全体は以下です。
scrape関数はその名の通りスクレイピングの処理をします。
urlにスクレイピングするサイトのURL、yearは年のデータを作成していくための変数です。
main部分はアクセスするためのURLを自動で作成してスクレイピング関数に処理させるためのコードになっています。
合計35行(空行含む)で14年分のデータが取得できます。
import pandas as pd
import time as t
import warnings
warnings.simplefilter("ignore")
def scrape(url,year):
data = pd.read_html(url)
df = data[2]
df3 = df[['日付','観客数']]
df3['観客数'] = df3['観客数'].str.replace('人','').str.replace(',','').str.replace('-','')
df3['観客数'] = df3['観客数'].str.strip()
df3.dropna(inplace=True)
df3['日付'] = df3['日付'].str[:-3]
df3['日付'] = pd.to_datetime(year + '年' + df3['日付'], format='%Y年%m月%d日')
return df3
if __name__ == "__main__":
start = t.time()
teams = ['swallows','baystars','tigers','giants','carp','dragons','buffaloes','marines','eagles','hawks','fighters','lions']
for team in teams:
data = pd.DataFrame()
for year in range(9,23):
s = '{:02}'.format(year)
print('https://baseball-freak.com/audience/'+ s + '/'+team+'.html')
df = scrape('https://baseball-freak.com/audience/'+ s + '/'+team+'.html','20'+s)
df['球団'] = team
data = pd.concat([data,df])
t.sleep(5)
data.to_csv('audience_data/' + team + '_audience.csv',index=False)
elapsed_time = t.time() - start
print ("elapsed_time:{0:.3f}".format(elapsed_time) + "[sec]")
コード解説
ライブラリインポートです。
主に使うライブラリはpandasのみですが、処理時間計測用にtime、警告表示を非表示にするためにwarningsを用います。
import pandas as pd
import time as t
import warnings
warnings.simplefilter("ignore")
スクレイピング関数はurlにあるデータを抽出してデータフレームに加工していく処理です。
urlはデータを取得するサイトです。
yearは年の数値が入ります。
pd.read_html(url)でサイトの表形式の部分を抽出します。
def scrape(url,year):
data = pd.read_html(url)
dataにサイトの表形式部分のデータを全て取ってきます。
data[2]の位置に観客数データが格納されているので、dfに代入します。
df = data[2]
取得する列のデータを指定してdf3に代入します。
必要なデータを絞りたい場合はここで取得する列を変更すれば良いです。
下記は取得できる全ての列です。
df3 = df[['日付','観客数','勝敗','スコア','対戦相手','先発投手','試合時間','球場']]
観客数のデータは文字列であり、「人」や「,」などが含まれています。
観客数は計算しやすい数値として扱いため、これらの文字列を削除します。
strip()では空白を削除し、欠損値のあるデータは削除します。
df3['観客数'] = df3['観客数'].str.replace('人','').str.replace(',','').str.replace('-','')
df3['観客数'] = df3['観客数'].str.strip()
df3.dropna(inplace=True)
日付列は年月日に曜日まであるので、曜日部分の文字列を削除します。
後ろ3文字が曜日の記載になっているので、df3['日付'].str[:-3]で後ろ3文字は除外できます。
除外後、pd.to_datetime(year + '年' + df3['日付'], format='%Y年%m月%d日')で日付データの方に変換します。
最後にreturnでデータフレーム形式で返します。
df3['日付'] = df3['日付'].str[:-3]
df3['日付'] = pd.to_datetime(year + '年' + df3['日付'], format='%Y年%m月%d日')
return df3
メイン処理部分です。
メインメソッドを宣言して始めます。
start変数にt.time()で時刻を取得します。
teamsにはURLのパーツとなる文字列を入れておきます。
サイトは各球団、年別にサイトが分かれています。
teamsのリストには各球団を識別するためのURLの一部を格納しておきます。
このサイトはチーム名で分けてくれているのでわかりやすいです。
if __name__ == "__main__":
start = t.time()
teams = ['swallows','baystars','tigers','giants','carp','dragons','buffaloes','marines','eagles','hawks','fighters','lions']
スクレイピング処理はfor文の2重ループで12球団の14年分の観客数を取得します。
最初のループでチームを指定するため、teamsリストから格納されている文字列を取得。
2つ目のループに入る前にデータフレーム形式の変数をdataとして初期化します。
2つ目のループは年を指定していきます。
スクレイピング先のサイトのURLはチームと年で分けられています。
年は一桁は09と表示としているため、0パディングした文字列をsに代入。
printでアクセスするURLを出力しています。(出力しなくても処理上問題はありません。)
scrape関数にurlと'20'+sを渡して、dfにデータセットが格納されます。
'20'+sで2009、2010・・・と年を西暦で渡します。
データ取得後、df['球団']=teamで球団列を追加します。
scrape関数は1年ごとデータを取得しますので、pd.concat()を用いて、データを追加していきます。
t.sleep(5)で5秒間処理を止めます。
処理を止めるのは、高速にURLアクセスを避けるためです。
5秒は長すぎかもしれません。
短くする場合は5より低い数値にすれば良いですが1秒より長めに設定しておくことをお勧めします。
内側のループを抜けたらdata.to_csv()でcsvファイル形式で保存します。
これで球団ごとの14年分のデータを取得することができます。
for team in teams:
data = pd.DataFrame()
for year in range(9,23):
s = '{:02}'.format(year)
print('https://baseball-freak.com/audience/'+ s + '/'+team+'.html')
df = scrape('https://baseball-freak.com/audience/'+ s + '/'+team+'.html','20'+s)
df['球団'] = team
data = pd.concat([data,df])
t.sleep(5)
data.to_csv('audience_data/' + team + '_audience.csv',index=False)
最後は時間計測のために、t.time()と処理の開始時に取得した時刻データstartの差を取ることで処理時間を計算します。
print ("elapsed_time:{0:.3f}".format(elapsed_time) + "[sec]")で処理にかかった時間を秒で出力して終了です。
5秒間の処理停止を設けてプログラムを実行すると約15分です。
elapsed_time = t.time() - start
print ("elapsed_time:{0:.3f}".format(elapsed_time) + "[sec]")
取得データ例
取得したデータは下のようになります。
観客数の他にも球場や対戦した球団、勝敗、スコア、先発投手、試合時間が取得できます。
まとめ
35行でプロ野球の観客数データを取得しました。
取得したデータでいろんな分析をしてみてください。
プログラムコード(有料)
本記事のプログラムコードをpythonファイルとnotebook形式で販売します。
よろしければサポートをよろしくお願いします。サポートいただいた資金は活動費に使わせていただきます。