見出し画像

Python SeleniumでNPB審判の出場記録をスクレイピングする②

6人制になる試合をどのように分岐していくか

前回で大分空いてしまいましたが枠組みは完成しました。6人制になる試合をどのように記述していくかが課題でしたがレギュラーシーズン、オールスター、CS、日本シリーズそれぞれ関数を作り処理すればよいのではと思いつきました。

#オールスター用のリストを追加する関数
def all_star_info():
       
   all_star_time_list.append(browser.find_element_by_css_selector("#game_stats > div.game_tit > time").text)
   all_star_place_list.append(browser.find_element_by_css_selector("#game_stats > div.game_tit > span").text)
   all_star_umpire_list.append(browser.find_element_by_class_name("referee_info").text)
   all_star_name_list.append(browser.find_element_by_css_selector("#game_stats > div.game_tit > h3").text)

   time.sleep(0.5)
   browser.back()
       
#オールスター用のデータを整理、それぞれのリストに追加、セルに記入していく関数
def all_cell_record():

   #取得したデータを格納したリストを一度文字列に変換してからsplitで再度リスト化しています
   Str_all_star_umpire_list =' '.join(all_star_umpire_list)
   Str_all_star_umpire_list = re.sub('[球審塁審線審(一)(二)(三)(左)(右)、:]','',Str_all_star_umpire_list)
    
    #再びリスト化する
   new_all_star_umpire_list = Str_all_star_umpire_list.split(' ')
   
   for j in range(len(new_all_star_umpire_list)):

       #リストの位置が0と6の倍数のときはUK_umpire(球審)に追加
       if j ==0 or j % 6  ==0:
           all_UK_umpire.append(new_all_star_umpire_list[j])
   
       #リストの位置が0と6の倍数+1のときはfirst_umpire(一塁塁審)に追加
       elif j ==1 or j % 6 ==1:
           all_first_umpire.append(new_all_star_umpire_list[j])
       #リストの位置が0と4の倍数+2のときはsecond_umpire(二塁塁審)に追加
       elif j ==2 or j % 6  ==2:
           all_second_umpire.append(new_all_star_umpire_list[j])
       #third_umpire(三塁塁審)に追加
       elif j ==3 or j % 6 ==3:
            all_third_umpire.append(new_all_star_umpire_list[j])
        #left_umpire(線審(左))に追加
       elif j ==4 or j % 6 == 4:
           all_left_umpire.append(new_all_star_umpire_list[j])
       #right_umpire(線審(右))に追加
       elif j ==5 or j % 6 ==5:
           all_right_umpire.append(new_all_star_umpire_list[j])

   #シート名を保存
   ws2 = wb.create_sheet('オールスター')

   ws2['A1']= '日時'
   ws2['B1']= '試合'
   ws2['C1']= '球場'
   ws2['D1']= '球審'
   ws2['E1']= '一塁'
   ws2['F1']= '二塁'
   ws2['G1']= '三塁'
   ws2['H1']= '線審(左)'
   ws2['I1']= '線審(右)'

   for k in range(len(all_star_time_list)):
       #openpyxlで出力する用の記述
       ws2.cell(row=k+2,column=1,value=all_star_time_list[k])
       ws2.cell(row=k+2,column=2,value=all_star_name_list[k])
       ws2.cell(row=k+2,column=3,value=all_star_place_list[k])
       ws2.cell(row=k+2,column=4,value=all_UK_umpire[k])
       ws2.cell(row=k+2,column=5,value=all_first_umpire[k])
       ws2.cell(row=k+2,column=6,value=all_second_umpire[k])
       ws2.cell(row=k+2,column=7,value=all_third_umpire[k])
       ws2.cell(row=k+2,column=8,value=all_left_umpire[k])
       ws2.cell(row=k+2,column=9,value=all_right_umpire[k])

このような関数をそれぞれ作ります。シートも試合の種類に分けて格納します。

そして、試合名をリストに入れて条件分岐で「試合名にオールスターが含まれていたらdef all_star_info()とdef all_star_cell_record()を実行」というように分けていきます。シートごとに試合の種類が分かれて記述されていくので見やすくなります。


#ここでURLを変えながらループしていきます
for i in range(3,11):
   #NPBのサイト
   url1 = "https://npb.jp/"
   #9月までのURL
   if i <10:
       url2 = "https://npb.jp/games/2016/schedule_0"+str(i)+"_detail.html"
   #10月以降のURL
   elif i >=10:
       url2 = "https://npb.jp/games/2016/schedule_"+str(i)+"_detail.html"
   #NPBのサイトを表示
   browser.get(url1)

   #今日分の試合数を取得します
   today_score_box_length =len(browser.find_elements_by_class_name("state"))

   browser.get(url2)
   #過去の試合数を取得します
   score_box_length =len(browser.find_elements_by_class_name("state"))


   if today_score_box_length>0:
       #試合がある日に取得すると今日分の試合の結果も出力されてしまうのでrangeで範囲を限定します
       for i in range(today_score_box_length,score_box_length):  

           browser.find_elements_by_class_name("state")[i].click()  
       
           if 'オールスター' in browser.find_element_by_css_selector("#game_stats > div.game_tit > h3").text:
               
               all_star_info()
               
           elif 'CS' in browser.find_element_by_css_selector("#game_stats > div.game_tit > h3").text:
               CS_info()
           elif '日本シリーズ' in browser.find_element_by_css_selector("#game_stats > div.game_tit > h3").text:
               nihon_info()
           else:
               game_info()

   #試合がない日の動作
   else:
       for i in range(score_box_length):

           browser.find_elements_by_class_name("state")[i].click()

           if 'オールスター' in browser.find_element_by_css_selector("#game_stats > div.game_tit > h3").text:

               all_star_info()
               

           elif 'CS' in browser.find_element_by_css_selector("#game_stats > div.game_tit > h3").text:
               CS_info()
           elif '日本シリーズ' in browser.find_element_by_css_selector("#game_stats > div.game_tit > h3").text:
               nihon_info()
           else:
               game_info() 
      

試合がある日は最新の試合も取得されてしまうので今日の試合数から取得したい月の最終試合までに絞ります。今までおまじないのように書いていたfor i in range()の使い方がはっきり理解できました。これでこのスクリプトを実行するとexcelに取得したい年の審判の出場記録を出力することができます。

理解は例示の試金石

この一連のスクリプトを会社の人たちに見てもらったところ、「これをゼロから作る熱量がすごいです。」とドン引きされました(笑)。flaskやjava script、データベースなどを使って審判ファンの人たちに公開したらいいのでは、とアドバイスを頂いたので、今後はWEBページを作成してこの取得したデータを公開するところまでプログラミングの勉強がてらしていきたいなと思います。4月から勉強してきてできたらいいなと思っていたことが割と早く達成することができて自分でも驚いています。

文系でプログラミングなんてやっていけるのか不安に思っていましたが一つ形にできたので大きな自信になりました。尊敬する作家・数学学者の結城浩さんの著書「数学ガール」シリーズによく「理解は例示の試金石」という言葉が登場します。自分が何かを理解できているかどうかを確認するために例を作ってみるというものです。このスクリプトを作るときに何度もエラーが出てどうしてうまくいかないんだ、これで合っているはず…とへこむことがあったのですが、この言葉を呟きながら、例を作ってちゃんと動くか確かめてみる作業をして少しずつ前へ前へ進んでいくことができました。

学生時代は「分からないこと」にぶつかってしまったら「私には理解できない、得意な分かる科目だけ勉強すればいいんだ」と言い訳をして逃げてしまっていましたが、今初めて「分からないこと」を前にしても逃げずに何回も同じ文章を読んだり自分が理解できるところからしてみて、小さな例を作っては考えることを繰り返すことで「分からないことを理解する」ことができるようになりました。

これからも何万回もエラーを出して頭を抱えることがあるとは思いますがプログラミング学習を続けていきます。

#プロ野球 #NPB審判 #審判 #python #selenium #プログラミング初心者 #結城浩 #理解は例示の試金石 #審判出場記録自動スクリプト #プログラミング #NPB #野球 #スポーツ

この記事が気に入ったらサポートをしてみませんか?