1
- from os import name
2
- import re
3
1
import requests
4
2
from typing import Dict , List , Any , Union
5
3
from cachecontrol import CacheControl
6
4
from fuzzywuzzy import fuzz , process
5
+ import pandas as pd
6
+ import json
7
7
8
8
9
9
class AmericanSoccerAnalysis :
@@ -20,34 +20,31 @@ def __init__(self) -> None:
20
20
21
21
self .session = CACHE_SESSION
22
22
self .base_url = self .BASE_URL
23
- self .players = self ._get_all_ids ("player" )
24
- self .teams = self ._get_all_ids ("team" )
25
- self .stadia = self ._get_all_ids ("stadia" )
26
- self .managers = self ._get_all_ids ("manager" )
27
- self .referees = self ._get_all_ids ("referee" )
28
-
29
- def _get_all_ids (self , type : str ) -> Dict [ str , str ] :
30
- """Creates a dictionary where keys are names and values
31
- are corresponding ids .
32
-
33
- :param type: type of ids to get
34
- :returns: dictionary
23
+ self .players = self ._get_all ("player" )
24
+ self .teams = self ._get_all ("team" )
25
+ self .stadia = self ._get_all ("stadia" )
26
+ self .managers = self ._get_all ("manager" )
27
+ self .referees = self ._get_all ("referee" )
28
+
29
+ def _get_all (self , type : str ) -> pd . DataFrame :
30
+ """Gets all the data for a specific type and
31
+ stores it in a dataframe .
32
+
33
+ :param type: type of data to get
34
+ :returns: dataframe
35
35
"""
36
- all_ids = {}
36
+ df = pd . DataFrame ([])
37
37
for league in self .LEAGUES :
38
38
if type == "stadia" :
39
- url = f"{ self .BASE_URL } { league } /{ type } "
40
- type = "stadium"
39
+ url = f"{ self .BASE_URL } { league } /stadia"
41
40
else :
42
41
url = f"{ self .BASE_URL } { league } /{ type } s"
43
42
response = self .session .get (url ).json ()
44
- for resp in response :
45
- name = resp .get (f"{ type } _name" , "None" )
46
- name_id = resp .get (f"{ type } _id" , "None" )
47
- all_ids .update ({name : name_id })
48
- if type == "stadium" :
49
- type = "stadia"
50
- return all_ids
43
+ # Convert list of objects to JSON
44
+ resp_df = pd .read_json (json .dumps (response , default = lambda x : x .__dict__ ))
45
+ resp_df = resp_df .assign (competition = league )
46
+ df = df .append (resp_df )
47
+ return df
51
48
52
49
def _convert_name_to_id (self , type : str , name : str ) -> Union [str , int ]:
53
50
"""Converts the name of a player, manager, stadium, referee or team
@@ -60,31 +57,31 @@ def _convert_name_to_id(self, type: str, name: str) -> Union[str, int]:
60
57
min_score = 70
61
58
if type == "player" :
62
59
lookup = self .players
63
- names = self .players . keys ()
60
+ names = self .players [ "player_name" ]. to_list ()
64
61
elif type == "manager" :
65
62
lookup = self .managers
66
- names = self .managers . keys ()
63
+ names = self .managers [ "manager_name" ]. to_list ()
67
64
elif type == "stadium" :
68
65
lookup = self .stadia
69
- names = self .stadia . keys ()
66
+ names = self .stadia [ "stadium_name" ]. to_list ()
70
67
elif type == "referee" :
71
68
lookup = self .referees
72
- names = self .referees . keys ()
69
+ names = self .referees [ "referee_name" ]. to_list ()
73
70
elif type == "team" :
74
71
lookup = self .teams
75
- names = self .teams . keys ()
72
+ names = self .teams [ "team_name" ]. to_list ()
76
73
77
74
matches = process .extractOne (name , names , scorer = fuzz .partial_ratio )
78
75
if matches :
79
- if matches [1 ] > min_score :
80
- lookup_id = matches [0 ]
76
+ if matches [1 ] >= min_score :
77
+ name = matches [0 ]
81
78
else :
82
- print (f"No match found for { name } " )
79
+ print (f"No match found for { name } due to score " )
83
80
return ""
84
81
else :
85
82
print (f"No match found for { name } " )
86
83
return ""
87
- matched_id = lookup .get ( lookup_id )
84
+ matched_id = lookup .loc [ lookup [ f" { type } _name" ] == name , f" { type } _id" ]. iloc [ 0 ]
88
85
return matched_id
89
86
90
87
def _convert_names_to_ids (
@@ -106,101 +103,161 @@ def _convert_names_to_ids(
106
103
ids .append (self ._convert_name_to_id (type , n ))
107
104
return ids
108
105
106
+ def _check_leagues (self , leagues : Union [str , List [str ]]):
107
+ """Validates the leagues parameter
108
+
109
+ :param leagues: league abbreviation or list of league abbreviations
110
+ """
111
+ if isinstance (leagues , list ):
112
+ if not all (l in leagues for l in self .LEAGUES ):
113
+ print (
114
+ f"Leagues are limited only to the following options: { self .LEAGUES .join (',' )} ."
115
+ )
116
+ exit ()
117
+ else :
118
+ if leagues not in self .LEAGUES :
119
+ print (
120
+ f"Leagues are limited only to the following options: { self .LEAGUES .join (',' )} ."
121
+ )
122
+ exit ()
123
+
124
+ def _check_ids_names (
125
+ self , ids : Union [str , List [str ]], names : Union [str , List [str ]]
126
+ ):
127
+ """Makes sure only ids or names are passed to a function and verifies
128
+ they are the right data type.
129
+
130
+ :param ids: a single id or list of ids
131
+ :param names: a single name or list of names
132
+ """
133
+ if ids and names :
134
+ print ("Please specify only IDs or names, not both." )
135
+ exit ()
136
+
137
+ if ids :
138
+ if not isinstance (ids , str ) and not isinstance (ids , list ):
139
+ print ("IDs must be passed as a string or list of strings." )
140
+ exit ()
141
+
142
+ if names :
143
+ if not isinstance (names , str ) and not isinstance (names , list ):
144
+ print ("Names must be passed as a string or list of names." )
145
+ exit ()
146
+
147
+ def _filter_entity (
148
+ self ,
149
+ entity_all : pd .DataFrame ,
150
+ entity_type : str ,
151
+ leagues : Union [str , List [str ]],
152
+ ids : Union [str , List [str ]] = None ,
153
+ names : Union [str , List [str ]] = None ,
154
+ ) -> List [Dict [str , Any ]]:
155
+ """Filters a dataframe based on the arguments given.
156
+
157
+ :param entity_all: a dataframe containing the complete set of data
158
+ :param entity_type: the type of data
159
+ :param ids: a single id or list of ids
160
+ :param names: a single name or list of names
161
+ :returns: list of dictionaries, e.g. a dataframe converted to JSON
162
+ """
163
+ self ._check_leagues (leagues )
164
+ self ._check_ids_names (ids , names )
165
+
166
+ entity = entity_all
167
+
168
+ if names :
169
+ converted_ids = self ._convert_names_to_ids (entity_type , names )
170
+ else :
171
+ converted_ids = ids
172
+
173
+ if isinstance (leagues , str ):
174
+ leagues = [leagues ]
175
+ if isinstance (converted_ids , str ):
176
+ converted_ids = [converted_ids ]
177
+
178
+ entity = entity [entity ["competition" ].isin (leagues )]
179
+
180
+ if converted_ids :
181
+ entity = entity [entity [f"{ entity_type } _id" ].isin (converted_ids )]
182
+
183
+ return entity .to_json (orient = "records" )
184
+
109
185
def get_stadia (
110
- self , league : str , names : Union [str , List [str ]] = None
186
+ self ,
187
+ leagues : Union [str , List [str ]],
188
+ ids : Union [str , List [str ]] = None ,
189
+ names : Union [str , List [str ]] = None ,
111
190
) -> List [Dict [str , Any ]]:
112
191
"""Get information associated with stadia
113
192
114
- :param league: league abbreviation
193
+ :param leagues: league abbreviation or a list of league abbreviations
194
+ :param ids: a single stadium id or a list of stadia ids (optional)
115
195
:param names: a single stadium name or a list of stadia names (optional)
116
196
:returns: list of dictionaries
117
197
"""
118
- ids = self ._convert_names_to_ids ("stadium" , names )
119
- if isinstance (ids , str ):
120
- stadia_url = f"{ self .base_url } { league } /stadia?stadium_id={ ids } "
121
- elif isinstance (ids , list ):
122
- stadia_url = f"{ self .base_url } { league } /stadia?stadium_id={ ',' .join (ids )} "
123
- else :
124
- stadia_url = f"{ self .base_url } { league } /stadia"
125
- response = self .session .get (stadia_url )
126
- return response .json ()
198
+ stadia = self ._filter_entity (self .stadia , "stadium" , leagues , ids , names )
199
+ return stadia
127
200
128
201
def get_referees (
129
- self , league : str , names : Union [str , List [str ]] = None
202
+ self ,
203
+ leagues : Union [str , List [str ]],
204
+ ids : Union [str , List [str ]] = None ,
205
+ names : Union [str , List [str ]] = None ,
130
206
) -> List [Dict [str , Any ]]:
131
207
"""Get information associated with referees
132
208
133
- :param league: league abbreviation
209
+ :param leagues: league abbreviation or a list of league abbreviations
210
+ :param ids: a single referee id or a list of referee ids (optional)
134
211
:param names: a single referee name or a list of referee names (optional)
135
212
:returns: list of dictionaries
136
213
"""
137
- ids = self ._convert_names_to_ids ("referee" , names )
138
- if isinstance (ids , str ):
139
- referees_url = f"{ self .base_url } { league } /referees?referee_id={ ids } "
140
- elif isinstance (ids , list ):
141
- referees_url = (
142
- f"{ self .base_url } { league } /referees?referee_id={ ',' .join (ids )} "
143
- )
144
- else :
145
- referees_url = f"{ self .base_url } { league } /referees"
146
- response = self .session .get (referees_url )
147
- return response .json ()
214
+ referees = self ._filter_entity (self .referees , "referee" , leagues , ids , names )
215
+ return referees
148
216
149
217
def get_managers (
150
- self , league : str , names : Union [str , List [str ]] = None
218
+ self ,
219
+ leagues : Union [str , List [str ]],
220
+ ids : Union [str , List [str ]] = None ,
221
+ names : Union [str , List [str ]] = None ,
151
222
) -> List [Dict [str , Any ]]:
152
223
"""Get information associated with managers
153
224
154
- :param league: league abbreviation
155
- :param names: a single manager name or list of manager names (optional)
225
+ :param leagues: league abbreviation or a list of league abbreviations
226
+ :param ids: a single referee id or a list of referee ids (optional)
227
+ :param names: a single referee name or a list of referee names (optional)
156
228
:returns: list of dictionaries
157
229
"""
158
- ids = self ._convert_names_to_ids ("manager" , names )
159
- if isinstance (ids , str ):
160
- managers_url = f"{ self .base_url } { league } /managers?manager_id={ ids } "
161
- elif isinstance (ids , list ):
162
- managers_url = (
163
- f"{ self .base_url } { league } /managers?manager_id={ ',' .join (ids )} "
164
- )
165
- else :
166
- managers_url = f"{ self .base_url } { league } /managers"
167
- response = self .session .get (managers_url )
168
- return response .json ()
230
+ managers = self ._filter_entity (self .managers , "manager" , leagues , ids , names )
231
+ return managers
169
232
170
233
def get_teams (
171
- self , league : str , names : Union [str , List [str ]]
234
+ self ,
235
+ leagues : Union [str , List [str ]],
236
+ ids : Union [str , List [str ]] = None ,
237
+ names : Union [str , List [str ]] = None ,
172
238
) -> List [Dict [str , Any ]]:
173
239
"""Get information associated with teams
174
240
175
- :param league: league abbreviation
176
- :param names: a single team name or list of team names (optional)
241
+ :param leagues: league abbreviation or a list of league abbreviations
242
+ :param ids: a single team id or a list of team ids (optional)
243
+ :param names: a single team name or a list of team names (optional)
177
244
:returns: list of dictionaries
178
245
"""
179
- ids = self ._convert_names_to_ids ("team" , names )
180
- if isinstance (ids , str ):
181
- teams_url = f"{ self .base_url } { league } /teams?team_id={ ids } "
182
- if isinstance (ids , list ):
183
- teams_url = f"{ self .base_url } { league } /teams?team_id={ ',' .join (ids )} "
184
- else :
185
- teams_url = f"{ self .base_url } { league } /teams"
186
- response = self .session .get (teams_url )
187
- return response .json ()
246
+ teams = self ._filter_entity (self .teams , "team" , leagues , ids , names )
247
+ return teams
188
248
189
249
def get_players (
190
- self , league : str , names : Union [str , List [str ]]
250
+ self ,
251
+ leagues : Union [str , List [str ]],
252
+ ids : Union [str , List [str ]] = None ,
253
+ names : Union [str , List [str ]] = None ,
191
254
) -> List [Dict [str , Any ]]:
192
255
"""Get information associated with players
193
256
194
- :param league: league abbreviation
195
- :param names: a single player name or list of player names (optional)
257
+ :param league: league abbreviation or a list of league abbreviations
258
+ :param ids: a single player id or a list of player ids (optional)
259
+ :param names: a single player name or a list of player names (optional)
196
260
:returns: list of dictionaries
197
261
"""
198
- ids = self ._convert_names_to_ids ("player" , names )
199
- if isinstance (ids , str ):
200
- players_url = f"{ self .base_url } { league } /players?player_id={ ids } "
201
- if isinstance (ids , list ):
202
- players_url = f"{ self .base_url } { league } /players?player_id={ ',' .join (ids )} "
203
- else :
204
- players_url = f"{ self .base_url } { league } /players"
205
- response = self .session .get (players_url )
206
- return response .json ()
262
+ players = self ._filter_entity (self .players , "player" , leagues , ids , names )
263
+ return players
0 commit comments