nba_playoffs_game_updater.py 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229
  1. #!/usr/bin/env python3
  2. import gspread
  3. from oauth2client.service_account import ServiceAccountCredentials
  4. import datetime
  5. import time
  6. from nba_api.stats.static import players
  7. from nba_api.stats.endpoints import playergamelog
  8. spreadsheet_key = '1QBQvGSMesox1gwjpaoK-0-p3n-c4I_L73PWCggjdayM' # 2019 Official
  9. #spreadsheet_key = '14pHOScaGXvN83iCca6_5p6QoViYvo223cIJD9nnl7TI' # 2019 Test
  10. json_keyfile = 'NBA Playoffs Game-1f9a46f0715c.json'
  11. current_day = 'today' # today, else:
  12. #current_day = datetime.date(2018, 4, 15) # set date manually
  13. nba_cooldown = 2 # in seconds, don't hammer the NBA.com API too hard
  14. ###############################################################################
  15. def getWorksheet(spreadsheet_key, json_keyfile):
  16. scope = ['https://spreadsheets.google.com/feeds',
  17. 'https://www.googleapis.com/auth/drive']
  18. credentials = ServiceAccountCredentials.from_json_keyfile_name(json_keyfile, scope)
  19. gc = gspread.authorize(credentials)
  20. spreadsheet = gc.open_by_key(spreadsheet_key)
  21. worksheet = spreadsheet.get_worksheet(0)
  22. return worksheet
  23. def setDates(current_day):
  24. if current_day == 'today':
  25. # in case games go past midnight
  26. current_date = datetime.datetime.now() - datetime.timedelta(hours=3)
  27. current_date = current_date.date()
  28. else:
  29. current_date = current_day
  30. url_date = current_date.strftime('%m/%d/%Y')
  31. current_year = current_date.year
  32. if current_date.month > 6:
  33. current_season = '{}-{}'.format(str(current_year),
  34. str(current_year + 1)[2:])
  35. else:
  36. current_season = '{}-{}'.format(str(current_year - 1),
  37. str(current_year)[2:])
  38. return url_date, current_season, current_date
  39. def getFirstRowLastRow(worksheet, current_date):
  40. date_col_values = worksheet.col_values(1) # get all date cell values from column 1
  41. final_row = len(date_col_values) # get number of rows in spreadsheet
  42. date_cells = worksheet.range('A4:A'+str(final_row)) # get all date cells
  43. first_row = ""
  44. last_row = ""
  45. for date_cell in date_cells:
  46. if first_row != "":
  47. if date_cell.row == final_row:
  48. last_row = final_row
  49. break
  50. elif date_cell.value != "":
  51. last_row = date_cell.row - 1
  52. break
  53. continue
  54. elif date_cell.value != "":
  55. date_cell_day = datetime.datetime.strptime('{} {}'.format(date_cell.value,
  56. str(current_date.year)),
  57. '%A, %B %d %Y')
  58. date_cell_day = date_cell_day.date()
  59. if date_cell_day == current_date:
  60. first_row = date_cell.row
  61. return first_row, last_row
  62. def parsePlayersCells(todays_cells):
  63. player_cells = []
  64. player_names = []
  65. for cell in todays_cells:
  66. if cell.col == 3 and cell.value != "" and cell.value[-7:] != "-FIX!!!":
  67. player_cells.append(cell)
  68. player_name = cleanPlayerName(cell)
  69. player_names.append(player_name)
  70. player_names_unique = list(dict.fromkeys(player_names))
  71. return player_cells, player_names_unique
  72. def cleanPlayerName(player_cell):
  73. raw_name = player_cell.value
  74. first_name_last_name = raw_name.split()
  75. first_name = first_name_last_name[0]
  76. first_name = first_name.replace('.', '')
  77. last_name = first_name_last_name[1]
  78. player_name = first_name + ' ' + last_name
  79. return player_name
  80. def getPlayerStats(player_id, url_date, current_season):
  81. player_game_logs = playergamelog.PlayerGameLog(player_id=player_id,
  82. league_id_nullable='00',
  83. season_type_all_star='Playoffs',
  84. date_from_nullable=url_date,
  85. date_to_nullable=url_date)
  86. player_game_logs = player_game_logs.get_dict()
  87. player_game_logs_results = player_game_logs.get('resultSets')[0]
  88. player_game_logs_headers = player_game_logs_results.get('headers')
  89. # if player has no stats for this day, list will be empty
  90. if len(player_game_logs_results.get('rowSet')) < 1:
  91. player_stats_dict = None
  92. else:
  93. player_game_logs_values = player_game_logs_results.get('rowSet')[0]
  94. player_stats_dict = dict(zip(player_game_logs_headers, player_game_logs_values))
  95. return player_stats_dict
  96. def buildStatsDict(player_names_unique, url_date, current_season):
  97. stats_dict = {}
  98. for player_name in player_names_unique:
  99. player_info = players.find_players_by_full_name(player_name)
  100. if len(player_info) < 1:
  101. print("\nPlayer \"" + player_name + "\" not found, please fix name!")
  102. stats_dict[player_name] = "Fix Name!"
  103. continue
  104. player_id = player_info[0].get('id')
  105. stats_dict[player_name] = getPlayerStats(player_id, url_date, current_season)
  106. print('{} {}{} {}{}'.format('Got', player_name, '\'s (ID:', str(player_id), ') stats from NBA.com'))
  107. time.sleep(nba_cooldown)
  108. return stats_dict
  109. def updatePlayerStatsLocal(todays_cells, player_cell, player_stats, update, player_update):
  110. for cell in todays_cells:
  111. if cell.row == player_cell.row:
  112. if (cell.col == 4 and player_stats.get("PTS") != "" and
  113. str(cell.value) != str(player_stats.get("PTS"))):
  114. cell.value = str(player_stats.get("PTS"))
  115. update = True
  116. player_update = True
  117. elif (cell.col == 5 and player_stats.get("REB") != "" and
  118. str(cell.value) != str(player_stats.get("REB"))):
  119. cell.value = str(player_stats.get("REB"))
  120. update = True
  121. player_update = True
  122. elif (cell.col == 6 and player_stats.get("AST") != "" and
  123. str(cell.value) != str(player_stats.get("AST"))):
  124. cell.value = str(player_stats.get("AST"))
  125. update = True
  126. player_update = True
  127. elif (cell.col == 7 and player_stats.get("STL") != "" and
  128. str(cell.value) != str(player_stats.get("STL"))):
  129. cell.value = str(player_stats.get("STL"))
  130. update = True
  131. player_update = True
  132. elif (cell.col == 8 and player_stats.get("BLK") != "" and
  133. str(cell.value) != str(player_stats.get("BLK"))):
  134. cell.value = str(player_stats.get("BLK"))
  135. update = True
  136. player_update = True
  137. elif (cell.col == 9 and player_stats.get("TOV") != "" and
  138. str(cell.value) != str(player_stats.get("TOV"))):
  139. cell.value = str(player_stats.get("TOV"))
  140. update = True
  141. player_update = True
  142. elif (cell.col == 10 and player_stats.get("WL") != "" and
  143. str(cell.value) != str(player_stats.get("WL"))):
  144. cell.value = str(player_stats.get("WL"))
  145. update = True
  146. player_update = True
  147. return todays_cells, update, player_update
  148. if __name__ == "__main__":
  149. while True:
  150. url_date, current_season, current_date = setDates(current_day)
  151. print("Date: " + str(current_date))
  152. # open worksheet, find today's action, and create unique list of players
  153. try:
  154. worksheet = getWorksheet(spreadsheet_key, json_keyfile)
  155. first_row, last_row = getFirstRowLastRow(worksheet, current_date)
  156. if first_row == "":
  157. print("No games today! Pausing for 1000 seconds...")
  158. time.sleep(1000)
  159. continue
  160. todays_cells = worksheet.range(first_row, 3, last_row, 10)
  161. player_cells, player_names_unique = parsePlayersCells(todays_cells)
  162. print("Today's players:", end=' ', flush=True)
  163. print(player_names_unique)
  164. except gspread.exceptions.APIError:
  165. print("Google API overloaded, retrying in 10 seconds...")
  166. time.sleep(10)
  167. continue
  168. except:
  169. time.sleep(10)
  170. continue
  171. # Build stats dictionary from unique list of players
  172. print("Retrieving player stats from NBA.com...")
  173. stats_dict = buildStatsDict(player_names_unique, url_date, current_season)
  174. update = False # only update the sheet if it has changed
  175. for player_cell in player_cells:
  176. player_update = False # Return if individual player stats have changed
  177. player_name = cleanPlayerName(player_cell)
  178. if stats_dict.get(player_name) != None: # skip players with empty stats
  179. if stats_dict.get(player_name) == "Fix Name!":
  180. player_cell.value = str(player_cell.value) + "-FIX!!!"
  181. update = True
  182. else:
  183. player_stats = stats_dict.get(player_name)
  184. todays_cells, update, player_update = updatePlayerStatsLocal(todays_cells,
  185. player_cell,
  186. player_stats,
  187. update,
  188. player_update)
  189. if player_update == True:
  190. print("Updated " + player_name + "\'s stats")
  191. elif player_update == False:
  192. print(player_name + "\'s stats have not changed")
  193. if update == True:
  194. while True:
  195. try:
  196. print("Pushing changes to google sheet...")
  197. worksheet.update_cells(todays_cells, 'USER_ENTERED')
  198. break
  199. except gspread.exceptions.APIError:
  200. print("Google API overloaded, adding a 10 second delay...")
  201. time.sleep(10)
  202. continue
  203. else:
  204. print("No update necessary, pausing for 30 seconds...")
  205. time.sleep(30)
  206. continue # restart entire loop