
Python Seleniumを使ってNPB審判出場記録をスクレイピングする①
Pythonで何作る?
プログラミング自体はjavaを就職する前に少しと会社研修でCをちょっとかじった程で何にも作れなくていざ全体でPythonを勉強しましょうとなった時にさすがにまずい、何か作らないとと焦っていました。
そんな時に上司との面談で「プログラミングを上達するコツは自分が作りたいものを作ること」と言われたので作りたいものは何か考えた結果、「毎試合毎試合NPBのサイトにアクセスして6試合分審判がどこに出てるのか確認するのが面倒なので、プログラミングで自動化できないか」となりSeleniumを使ってデータスクレイピングするスクリプトを勉強のために作ろうとなりました。自分の記録のためにも作成した拙いコードを載せておきます。
「簡単!」とか謳っておきながら実際Seleniumの操作はめちゃくちゃ難しくて作るのやめちゃおうかなとも思ったのですが一から自分でプログラミング組む楽しさも知りました。
※スクレイピングはサイトによって違法になる場合もあるので個人の裁量でお願いします。
①試合詳細をクリックしてデータを取得して戻る、を繰り返す
ここが一番苦労したポイントです。同じクラス名が並んでいるのでfind_elementsで試合詳細ページの要素数(試合数)を取得し、更に月の試合詳細ページの要素数も取得し、月初めの試合からクリック出来るようにrange関数で指定しました。
#審判の出場情報を入手する関数
def get_umpire_info():
#試合がある日に取得すると今日分の試合の結果も出力されてしまうのでrangeで範囲を限定します
for i in range(today_score_box_length,score_box_length):
browser.find_elements_by_class_name("state")[i].click()
for j in range(1):
#試合の月日
time_list.insert(j,browser.find_element_by_css_selector("#game_stats > div.game_tit > time").text)
#球場
place_list.insert(j,browser.find_element_by_css_selector("#game_stats > div.game_tit > span").text)
#審判名
umpire_list.insert(j,browser.find_element_by_class_name("referee_info").text)
#どこの試合か(ヤクルトスワローズvs読売ジャイアンツなど)
name_list.insert(j,browser.find_element_by_css_selector("#game_stats > div.game_tit > h3").text)
time.sleep(0.3)
#一つ前の画面に戻る
browser.back()
insert(指定したい要素番号,リストに追加したい要素)で空のリストにスクレイピングしたデータをfor文でどんどん追加することができました。ただ出力するだけならそのままでもいいのですが審判名を余計な文字を省いて個人名別かつポジション別にセルに追加したかったので次のコードを入れます。
②スクレイピングしたデータを整理する
#取得したデータを格納したリストを一度文字列に変換してからsplitで再度リスト化しています
Str_umpire_list =' '.join(umpire_list)
Str_umpire_list =re.sub('[球塁審(一)(二)(三)、:]','',Str_umpire_list)
new_umpire_list = Str_umpire_list.split(' ')
#各ポジションのリストを作成
UK_umpire = []
first_umpire = []
second_umpire = []
third_umpire = []
#取得した審判名をif文を使って分岐してきます
for j in range(len(new_umpire_list)):
#リストの位置が0と4の倍数のときはUK_umpire(球審)に追加
if j ==0 or j % 4 ==0:
UK_umpire.insert(j,new_umpire_list[j])
#リストの位置が0と4の倍数+1のときはfirst_umpire(一塁塁審)に追加
elif j ==1 or j % 4 ==1:
first_umpire.insert(j,new_umpire_list[j])
#リストの位置が0と4の倍数+2のときはsecond_umpire(二塁塁審)に追加
elif j ==2 or j % 4 ==2:
second_umpire.insert(j,new_umpire_list[j])
#それ以外はthird_umpire(三塁塁審)に追加
elif j ==3 or j % 4 ==3:
third_umpire.insert(j,new_umpire_list[j])
#リストの要素を逆に出力するためにreverseしています
time_list.reverse()
name_list.reverse()
place_list.reverse()
UK_umpire.reverse()
first_umpire.reverse()
second_umpire.reverse()
third_umpire.reverse()
スクレイピングしたデータをそのまま出力すると「球審:小林 、塁審(一):川口 、塁審(二):石山 、塁審(三):津川」のようになります。一度文字列にしてからre.sub関数でいらない文字を省き、再度split関数でリストにしています。excelに出力するときに重複しないようにif文でリストの要素番号ごとに条件分岐しています。こうすることでポジション別に個人別にセルに入力することができます。
あとは①を月毎に繰り返していけばNPBのサイトに残っている分の試合情報から審判の出場記録をつけられる…!はずなのですがオールスターや日本シリーズがあると審判が二人増えるので上記の条件分岐を見直さなければいけません。Openpyxlで月別にシートを追加して、オールスターの場合はこの処理にする、といった条件分岐をすればいいのでしょうがまだまだそのあたりが出来ていません…が、Python勉強し始めて1か月近くこのスクリプトを作成してきて大分勉強になって自信がついてきました。関数や条件分岐や繰り返し処理も参考書を読んで分かった気になっていたところが実際に組んでみて
「そうか、だから関数はあると便利なんだ」「ループの動きってこういうことなんだ」
と理解することができました。色々機能を追加して最終的にはpandasでデータ分析できるところまでいけたらいいなと思っているので随時更新してきます。次はOpenpyxlでの出力についてまとめます。
#python #Selenium #データスクレイピング #プロ野球 #プログラミング #プログラミング初心者 #NPB #NPB審判 #野球 #審判