GetFootballData 0.1.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- GetFootballData/__init__.py +0 -0
- GetFootballData/fotmob_scraper.py +317 -0
- GetFootballData/scraper_utilities/__init__.py +0 -0
- GetFootballData/scraper_utilities/league_to_fotmob_map.py +11 -0
- GetFootballData/scraper_utilities/league_to_sofascore_map.py +393 -0
- GetFootballData/scraper_utilities/league_to_tm_map.py +6 -0
- GetFootballData/scraper_utilities/year_maps.py +89 -0
- GetFootballData/sofascore_scraper.py +472 -0
- GetFootballData/transfermarkt_scraper.py +288 -0
- getfootballdata-0.1.0.dist-info/METADATA +110 -0
- getfootballdata-0.1.0.dist-info/RECORD +14 -0
- getfootballdata-0.1.0.dist-info/WHEEL +5 -0
- getfootballdata-0.1.0.dist-info/licenses/LICENSE.md +665 -0
- getfootballdata-0.1.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,288 @@
|
|
|
1
|
+
import pandas as pd
|
|
2
|
+
import numpy as np
|
|
3
|
+
import requests
|
|
4
|
+
import time
|
|
5
|
+
import random
|
|
6
|
+
from bs4 import BeautifulSoup
|
|
7
|
+
from curl_cffi import requests as cffi_requests
|
|
8
|
+
from GetFootballData.scraper_utilities.league_to_tm_map import league_to_tm_dict
|
|
9
|
+
|
|
10
|
+
pd.set_option('display.max_columns', None)
|
|
11
|
+
pd.set_option('display.max_rows', None)
|
|
12
|
+
|
|
13
|
+
root_site = 'www.transfermarkt.com'
|
|
14
|
+
|
|
15
|
+
class TransfermarktScraper:
|
|
16
|
+
|
|
17
|
+
def __init__(self):
|
|
18
|
+
|
|
19
|
+
self.session = cffi_requests.Session(impersonate='chrome124')
|
|
20
|
+
|
|
21
|
+
self.session.headers.update({"accept": "application/json", "referer": f"https://{root_site}/"})
|
|
22
|
+
|
|
23
|
+
self.warm_up()
|
|
24
|
+
|
|
25
|
+
def warm_up(self):
|
|
26
|
+
"""Request fotmob page to familiarise session with fotmob."""
|
|
27
|
+
try:
|
|
28
|
+
self.session.get(f"https://{root_site}/", timeout=5)
|
|
29
|
+
time.sleep(random.uniform(1.5, 3.0))
|
|
30
|
+
except Exception as e:
|
|
31
|
+
print(f"Warm-up handshake warning: {e}")
|
|
32
|
+
|
|
33
|
+
def __get_player_id_df(self, year: int, league: str) -> pd.DataFrame:
|
|
34
|
+
|
|
35
|
+
'''
|
|
36
|
+
This method scrapes the transfermarkt ids, nationality and club for every player in the given league
|
|
37
|
+
|
|
38
|
+
:param year: starting year of the league (ex. 2025)
|
|
39
|
+
:param league: league name according to the package's naming conventions (ex. 'ENG-Premier League', 'FRA-Ligue 1')
|
|
40
|
+
:return: a dataframe containing: player_name, player_id, club_name, nation. If data can't be found, an empty dataframe is returned.
|
|
41
|
+
'''
|
|
42
|
+
|
|
43
|
+
league_dict = league_to_tm_dict[league]
|
|
44
|
+
league_name = league_dict[0]
|
|
45
|
+
league_code = league_dict[1]
|
|
46
|
+
|
|
47
|
+
url = f'https://{root_site}/{league_name}/tabelle/wettbewerb/{league_code}/saison_id/{str(year)}'
|
|
48
|
+
|
|
49
|
+
r = self.session.get(url)
|
|
50
|
+
|
|
51
|
+
if not r:
|
|
52
|
+
return pd.DataFrame()
|
|
53
|
+
|
|
54
|
+
soup = BeautifulSoup(r.text, "html.parser")
|
|
55
|
+
|
|
56
|
+
club_acronym_list = []
|
|
57
|
+
|
|
58
|
+
table = soup.find('table', {'class': 'items'})
|
|
59
|
+
|
|
60
|
+
for row in table.find_all('tr'):
|
|
61
|
+
link = row.find('a', href=True)
|
|
62
|
+
if not link:
|
|
63
|
+
continue
|
|
64
|
+
href = link['href']
|
|
65
|
+
club_acronym = href.split('/')[1]
|
|
66
|
+
club_id = href.split('/')[4]
|
|
67
|
+
club_name = link['title']
|
|
68
|
+
club_acronym_list.append([club_acronym, club_id, club_name])
|
|
69
|
+
|
|
70
|
+
name_id_list = []
|
|
71
|
+
|
|
72
|
+
club_counter = 0
|
|
73
|
+
|
|
74
|
+
for club_acronym in club_acronym_list:
|
|
75
|
+
|
|
76
|
+
club_name = club_acronym[2]
|
|
77
|
+
#squad_url = f'https://www.transfermarkt.com/{club_acronym[0]}/kader/verein/{club_acronym[1]}/plus/0/galerie/0?saison_id={year}'
|
|
78
|
+
squad_url = f'https://{root_site}/{club_acronym[0]}/kader/verein/{club_acronym[1]}/saison_id/{year}'
|
|
79
|
+
r = self.session.get(squad_url)
|
|
80
|
+
soup = BeautifulSoup(r.text, "html.parser")
|
|
81
|
+
table = soup.find('table', {'class': 'items'})
|
|
82
|
+
|
|
83
|
+
for row in table.find_all('table', {'class': 'inline-table'}):
|
|
84
|
+
link_area = row.find('td', {'class': 'hauptlink'})
|
|
85
|
+
if not link_area:
|
|
86
|
+
continue
|
|
87
|
+
link = link_area.find('a', href=True)
|
|
88
|
+
href = link['href']
|
|
89
|
+
player_id = href.split('/')[4]
|
|
90
|
+
player_name = link_area.get_text(strip=True)
|
|
91
|
+
|
|
92
|
+
parent_row = row.find_parent('tr')
|
|
93
|
+
|
|
94
|
+
nation = None
|
|
95
|
+
for area in parent_row.find_all('td', {'class': 'zentriert'}):
|
|
96
|
+
nation_image = area.find('img', class_='flaggenrahmen')
|
|
97
|
+
if not nation_image:
|
|
98
|
+
continue
|
|
99
|
+
nation = nation_image['title']
|
|
100
|
+
|
|
101
|
+
name_id_list.append((player_name, player_id, club_name, nation))
|
|
102
|
+
|
|
103
|
+
club_counter += 1
|
|
104
|
+
print(f'{club_counter}/{len(club_acronym_list)} teams complete.')
|
|
105
|
+
|
|
106
|
+
name_id_df = pd.DataFrame(name_id_list, columns=['player_name', 'player_id', 'club_name', 'nation']).set_index('player_name')
|
|
107
|
+
|
|
108
|
+
return name_id_df
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
def get_player_overview_df(self, year: int, league: str) -> pd.DataFrame:
|
|
113
|
+
|
|
114
|
+
dataframe = self.__get_player_id_df(year, league)
|
|
115
|
+
|
|
116
|
+
base_players_url = f'https://tmapi.transfermarkt.technology/players?'
|
|
117
|
+
|
|
118
|
+
team_list = dataframe['club_name'].unique().tolist()
|
|
119
|
+
|
|
120
|
+
final_player_dataframe = pd.DataFrame()
|
|
121
|
+
|
|
122
|
+
for team in team_list:
|
|
123
|
+
|
|
124
|
+
team_player_ids = dataframe[dataframe['club_name'] == team]['player_id'].tolist()
|
|
125
|
+
|
|
126
|
+
team_players_url = base_players_url
|
|
127
|
+
|
|
128
|
+
for player_id in team_player_ids:
|
|
129
|
+
|
|
130
|
+
team_players_url = team_players_url + f'ids[]={player_id}&'
|
|
131
|
+
|
|
132
|
+
team_players_url = team_players_url[:-1]
|
|
133
|
+
|
|
134
|
+
if team_players_url == base_players_url:
|
|
135
|
+
raise Exception(f'No team player ids found for {team}')
|
|
136
|
+
|
|
137
|
+
r = self.session.get(team_players_url)
|
|
138
|
+
|
|
139
|
+
player_data = r.json()['data']
|
|
140
|
+
|
|
141
|
+
team_data_list = []
|
|
142
|
+
|
|
143
|
+
for player in player_data:
|
|
144
|
+
|
|
145
|
+
club_assignment_list = [{}, {}]
|
|
146
|
+
for index, club_dict in enumerate(player['clubAssignments'][:2]): # Only go through first two assignments
|
|
147
|
+
club_assignment_list[index] = club_dict
|
|
148
|
+
|
|
149
|
+
data_dict = {
|
|
150
|
+
'player_name': player['name'],
|
|
151
|
+
'player_id': player['id'],
|
|
152
|
+
'age': player['lifeDates'].get('age', None),
|
|
153
|
+
'date_of_birth': player['lifeDates'].get('dateOfBirth', None),
|
|
154
|
+
'birth_place': player['birthPlaceDetails'].get('placeOfBirth', None),
|
|
155
|
+
'position': player['attributes'].get('position', {}).get('name', None),
|
|
156
|
+
'team': team,
|
|
157
|
+
'general_position': player['attributes'].get('position', {}).get('category', None),
|
|
158
|
+
'preferred_foot': player['attributes'].get('preferredFoot', {}).get('name', None),
|
|
159
|
+
'height': player['attributes'].get('height', None),
|
|
160
|
+
'contractEnd':player['attributes'].get('contractUntil', None),
|
|
161
|
+
'sponsor': player['attributes'].get('outfitter', {}).get('name', None),
|
|
162
|
+
'agent': player['attributes'].get('consultantAgency', {}).get('name', None),
|
|
163
|
+
'market_value': player.get('marketValueDetails', {}).get('current', {}).get('value', None),
|
|
164
|
+
'previous_market_value': player.get('marketValueDetails', {}).get('previous', {}).get('value', None),
|
|
165
|
+
'highest_market_value': player.get('marketValueDetails', {}).get('highest', {}).get('value', None),
|
|
166
|
+
'shirt_number': club_assignment_list[0].get('shirtNumber', None),
|
|
167
|
+
'debut': club_assignment_list[0].get('debut', None),
|
|
168
|
+
'is_captain': club_assignment_list[0].get('isCaptain', None),
|
|
169
|
+
'nt_shirt_number': club_assignment_list[1].get('shirtNumber', None),
|
|
170
|
+
'nt_debut': club_assignment_list[1].get('debut', None),
|
|
171
|
+
'is_nt_captain': club_assignment_list[1].get('isCaptain', None),
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
team_data_list.append(data_dict)
|
|
175
|
+
|
|
176
|
+
team_stats_df = pd.DataFrame(team_data_list)
|
|
177
|
+
final_player_dataframe = pd.concat([final_player_dataframe, team_stats_df])
|
|
178
|
+
|
|
179
|
+
final_player_dataframe.set_index('player_id', inplace=True)
|
|
180
|
+
|
|
181
|
+
#Set Nationality
|
|
182
|
+
final_player_dataframe = final_player_dataframe.merge(dataframe.reset_index()[['player_id', 'nation']], on='player_id', how='left')
|
|
183
|
+
|
|
184
|
+
return final_player_dataframe
|
|
185
|
+
|
|
186
|
+
|
|
187
|
+
def get_player_transfer_history(self, player_id: str) -> pd.DataFrame:
|
|
188
|
+
|
|
189
|
+
'''
|
|
190
|
+
:param player_id: transfermarkt's player id (as seen in the url of a player's profile)
|
|
191
|
+
:return: A pandas dataframe containing a row for every recorded transfer a given player has had according to transfermarkt. If there is no history, an empty dataframe is returned. Rows include;
|
|
192
|
+
|
|
193
|
+
|
|
194
|
+
Columns:
|
|
195
|
+
- source_name: source club
|
|
196
|
+
- destination_name: destination club
|
|
197
|
+
- source_club_id: source club transfermarkt id
|
|
198
|
+
- destination_club_id: destination club transfermarkt id
|
|
199
|
+
- source_competition: league code of source team
|
|
200
|
+
- destination_competition: league code of destination team
|
|
201
|
+
- contract_start_date: start of contract date
|
|
202
|
+
- contract_end_date: end of contract date
|
|
203
|
+
- season: year of the beginning of the season
|
|
204
|
+
- market_value_at_time: market value at the time of the transfer
|
|
205
|
+
- age: age of the player at the time of the transfer
|
|
206
|
+
- fee: fee of the transfer in euros (€)
|
|
207
|
+
- transfer_type: description of the nature of the transfer ex. loan. Column will not contain data if it is a normal transfer.
|
|
208
|
+
- fee_description: Extra description of the nature of the attached fee, ex. loan fee. Column will not contain data if it is a normal transfer.
|
|
209
|
+
'''
|
|
210
|
+
|
|
211
|
+
url = f"https://tmapi.transfermarkt.technology/transfer/history/player/{player_id}"
|
|
212
|
+
|
|
213
|
+
r = self.session.get(url) #Fetch transfer history page via URL
|
|
214
|
+
|
|
215
|
+
print(player_id)
|
|
216
|
+
|
|
217
|
+
try:
|
|
218
|
+
transfer_history = r.json()["data"]['history']['terminated']
|
|
219
|
+
except:
|
|
220
|
+
return pd.DataFrame()
|
|
221
|
+
|
|
222
|
+
|
|
223
|
+
|
|
224
|
+
club_id_set = set()
|
|
225
|
+
|
|
226
|
+
source_data = transfer_history[0]["transferSource"]
|
|
227
|
+
club_id_set.add(source_data["clubId"])
|
|
228
|
+
|
|
229
|
+
for row in transfer_history:
|
|
230
|
+
source_data = row["transferSource"]
|
|
231
|
+
destination_data = row["transferDestination"]
|
|
232
|
+
club_id_set.add(source_data["clubId"])
|
|
233
|
+
club_id_set.add(destination_data["clubId"])
|
|
234
|
+
|
|
235
|
+
club_url = f'https://tmapi.transfermarkt.technology/clubs?'
|
|
236
|
+
for club_id in club_id_set:
|
|
237
|
+
club_url = club_url + f'ids[]={club_id}&'
|
|
238
|
+
club_url = club_url[:-1]
|
|
239
|
+
|
|
240
|
+
|
|
241
|
+
for i in range(1,5):
|
|
242
|
+
try:
|
|
243
|
+
club_r = self.session.get(club_url) # Fetch club name data from transfermarkt api
|
|
244
|
+
club_data = club_r.json()["data"]
|
|
245
|
+
break
|
|
246
|
+
except requests.exceptions.RequestException as e:
|
|
247
|
+
print(e)
|
|
248
|
+
if i == 5:
|
|
249
|
+
print(f'Could not access transfermarkt club data from api.')
|
|
250
|
+
exit()
|
|
251
|
+
print(f'Request failed, retrying {i+1}/5 after 10 seconds')
|
|
252
|
+
time.sleep(10)
|
|
253
|
+
|
|
254
|
+
|
|
255
|
+
|
|
256
|
+
id_to_club_dict = {}
|
|
257
|
+
for row in club_data:
|
|
258
|
+
id_to_club_dict.update({row['id']:row['name']})
|
|
259
|
+
|
|
260
|
+
transfer_history_list = []
|
|
261
|
+
|
|
262
|
+
for row in transfer_history:
|
|
263
|
+
source_data = row["transferSource"]
|
|
264
|
+
destination_data = row["transferDestination"]
|
|
265
|
+
details_data = row["details"]
|
|
266
|
+
transfer_type_data = row['typeDetails']
|
|
267
|
+
entry = {'player_id': player_id,
|
|
268
|
+
'source_name': id_to_club_dict[source_data['clubId']],
|
|
269
|
+
'destination_name': id_to_club_dict[destination_data['clubId']],
|
|
270
|
+
'source_club_id': source_data['clubId'],
|
|
271
|
+
'destination_club_id': destination_data['clubId'],
|
|
272
|
+
'source_competition': source_data['competitionId'],
|
|
273
|
+
'destination_competition': destination_data['competitionId'],
|
|
274
|
+
'contract_start_date': details_data["date"],
|
|
275
|
+
'contract_end_date': details_data["contractUntilDate"],
|
|
276
|
+
'season': details_data.get("season").get('id'),
|
|
277
|
+
'market_value_at_time': details_data.get('marketValue', {}).get('value', np.nan),
|
|
278
|
+
'age': details_data["age"],
|
|
279
|
+
'fee': details_data.get('fee', {}).get('value', np.nan),
|
|
280
|
+
'transfer_type': transfer_type_data.get('name', np.nan),
|
|
281
|
+
'fee_description': transfer_type_data.get('feeDescription', np.nan),
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
transfer_history_list.append(entry)
|
|
285
|
+
|
|
286
|
+
transfer_history_df = pd.DataFrame(transfer_history_list).set_index('player_id')
|
|
287
|
+
|
|
288
|
+
return transfer_history_df
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: GetFootballData
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Scrapers for FotMob, SofaScore and Transfermarkt
|
|
5
|
+
Author: Max Newby
|
|
6
|
+
License-Expression: AGPL-3.0-or-later
|
|
7
|
+
Project-URL: Homepage, https://github.com/MaxNewby/GetFootballData
|
|
8
|
+
Keywords: football,soccer,scraper,analytics,datasets
|
|
9
|
+
Requires-Python: >=3.11
|
|
10
|
+
Description-Content-Type: text/markdown
|
|
11
|
+
License-File: LICENSE.md
|
|
12
|
+
Requires-Dist: beautifulsoup4>=4.15
|
|
13
|
+
Requires-Dist: curl_cffi>=0.16
|
|
14
|
+
Requires-Dist: numpy>=2.4
|
|
15
|
+
Requires-Dist: pandas>=3.0
|
|
16
|
+
Requires-Dist: requests>=2.34
|
|
17
|
+
Dynamic: license-file
|
|
18
|
+
|
|
19
|
+
# GetFootballData
|
|
20
|
+
|
|
21
|
+
This package contains classes to read data from Sofascore, FotMob and Transfermarkt.
|
|
22
|
+
|
|
23
|
+
To make it easier league naming conventions are derived from other packages such as ScraperFC to make this package more compatible with others.
|
|
24
|
+
|
|
25
|
+
Created by Max Newby
|
|
26
|
+
|
|
27
|
+
>[NOTE] about using the 'league_name' parameter
|
|
28
|
+
>
|
|
29
|
+
>
|
|
30
|
+
>To see the format in which the league_name parameter should be entered in, check the dictionary keys in any _map.py file inside scraper_utilities.
|
|
31
|
+
> Examples include; 'ENG-Premier League', 'ESP-La Liga', 'GER-Bundesliga'.
|
|
32
|
+
|
|
33
|
+
## <u>Using the Package:</u>
|
|
34
|
+
|
|
35
|
+
### Sofascore_scraper.py:
|
|
36
|
+
|
|
37
|
+
A SofascoreScraper object comes with the following methods:
|
|
38
|
+
|
|
39
|
+
`get_player_id_dicts(self, year: int, league_name: str) -> dict[int, dict[str, str | dict[int, str]]]`
|
|
40
|
+
|
|
41
|
+
This method returns a dictionary containing {team_id: team_data} pairs. Inside team_data, is the 'team_name' and another dictionary 'player_id_dict' that contains the {player_id, player_name} pairs.
|
|
42
|
+
|
|
43
|
+
year: Takes the starting year of the given season.
|
|
44
|
+
league_name: Takes the name of the given league in the given format.
|
|
45
|
+
|
|
46
|
+
return: a dictionary of team names mapping to dictionaries containing player ids and names in the format {team_id: {name: team_name, player_dict: {player_id: player_name, ...}}, ...}.
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
`get_player_metadata_df(self, year: int, league_name: str) -> pd.Dataframe`
|
|
50
|
+
|
|
51
|
+
This method returns a dataframe containing general data about each player in the league for a given season.
|
|
52
|
+
|
|
53
|
+
:param year: starting year of the given season.
|
|
54
|
+
:param league_name: name of the league according to the given format.
|
|
55
|
+
|
|
56
|
+
:return: a pd.DataFrame containing general data about each player in a given league (height, preferred foot, etc.).
|
|
57
|
+
|
|
58
|
+
`get_player_stat_df(self, year: int, league_name: str, stat_type='total', specific_stats=None, position_list=None, nationality_code_list=None, team_id_list=None, min_appearances=None, age=None, age_bound='EQ', home_or_away_only=None, preferred_foot=None) -> pd.DataFrame:`
|
|
59
|
+
|
|
60
|
+
This method will return a dataframe containing statistical data for every player in the league for that given season. Responses can be filtered using the parameters.
|
|
61
|
+
|
|
62
|
+
year: starting year of the league in the given format
|
|
63
|
+
league_name: name of the league in the wanted format
|
|
64
|
+
stat_type: 'total', 'per90', 'perGame'
|
|
65
|
+
specific_stats: accepts a list of specific stats to return. Stats can be listed as seen on sofascore, in a league->stats->detailed tab
|
|
66
|
+
position_list: accepts a list of positions to return. options ['G', 'D', 'M', 'F']
|
|
67
|
+
nationality_code_list: accepts a list of nationality codes to return.
|
|
68
|
+
team_id_list: enter a list of sofascore's team IDs to return data only from those teams.
|
|
69
|
+
min_appearances: min appearances of a player in the given league/year
|
|
70
|
+
age: age of the player in the given league/year
|
|
71
|
+
age_bound: options: 'LT', 'EQ', 'GT'
|
|
72
|
+
home_or_away_only: 'home', 'away'
|
|
73
|
+
preferred_foot: 'left', 'right'. Returns only players with the given preferred foot.
|
|
74
|
+
|
|
75
|
+
return: a dataframe containing all records of stat data of given filters, for players in a given season and league
|
|
76
|
+
|
|
77
|
+
### fotmob_scraper.py:
|
|
78
|
+
|
|
79
|
+
A FotmobScraper object comes with the following methods:
|
|
80
|
+
|
|
81
|
+
`get_player_data_df(self, year: int, league_name: str) -> pd.DataFrame`
|
|
82
|
+
|
|
83
|
+
This method scrapes statistical player data, for every player in the league for a given season
|
|
84
|
+
|
|
85
|
+
year: starting year of the league (ex. 2025)
|
|
86
|
+
league_name: league name in the package's standardised format: (ex. 'ENG-Premier League')
|
|
87
|
+
return: a pd.Dataframe instance containing the player data.
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
### transfermarkt_scraper.py:
|
|
92
|
+
|
|
93
|
+
A TransfermarktScraper object comes with the following methods:
|
|
94
|
+
|
|
95
|
+
`transfermarkt_scraper.get_player_transfer_history(self, player_id: str) -> pd.DataFrame:`
|
|
96
|
+
|
|
97
|
+
This method returns a dataframe containing a player's transfer history, and data such as fees and contract durations for each transfer.
|
|
98
|
+
|
|
99
|
+
player_id: transfermarkt's player id (as seen in the url of a player's profile)
|
|
100
|
+
return: A pandas dataframe containing a row for every recorded transfer a given player has had according to transfermarkt. If there is no history, an empty dataframe is returned. Rows include;
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
`transfermarkt_scraper.get_player_overview_df(self, year: int, league: str)`
|
|
104
|
+
|
|
105
|
+
This method scrapes general player data such as transfermarkt ids, nationality and club for every player in the given league
|
|
106
|
+
|
|
107
|
+
year: starting year of the league (ex. 2025)
|
|
108
|
+
league: league name according to the package's naming conventions (ex. 'ENG-Premier League', 'FRA-Ligue 1')
|
|
109
|
+
return: a dataframe containing: player_name, player_id, club_name, nation. If data can't be found, an empty dataframe is returned.
|
|
110
|
+
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
GetFootballData/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
2
|
+
GetFootballData/fotmob_scraper.py,sha256=J6WCSooIHvjpM4WXrlYY6wx0yJxYZIXYXfbqY0vxfLA,14925
|
|
3
|
+
GetFootballData/sofascore_scraper.py,sha256=HGc6-k-crftIXVfkreoORsABdMtMsGVKiOXsC8DOJg0,20556
|
|
4
|
+
GetFootballData/transfermarkt_scraper.py,sha256=VRJtkGSWj9qQ3vQm_ehPVSUvbhv7Qkc1XCDO5Vq4yXk,12067
|
|
5
|
+
GetFootballData/scraper_utilities/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
6
|
+
GetFootballData/scraper_utilities/league_to_fotmob_map.py,sha256=HK6vs_raRvRGYAxgBvFlnWbnKVyqGvigR93VWC66APc,783
|
|
7
|
+
GetFootballData/scraper_utilities/league_to_sofascore_map.py,sha256=_t2EHCprmMfCJ9hbf1swm9OQSDY4_LNfdgklgZIZ5Y4,32945
|
|
8
|
+
GetFootballData/scraper_utilities/league_to_tm_map.py,sha256=HKSChPmTmbc3NTloI3SQW_x7tcxOGBKlWOCoD9fiFKk,320
|
|
9
|
+
GetFootballData/scraper_utilities/year_maps.py,sha256=Ia33YqPyokMlRq51vhijFKq7ab7eZiCxGY1YdcqSxUM,1768
|
|
10
|
+
getfootballdata-0.1.0.dist-info/licenses/LICENSE.md,sha256=sxfZgBWf-IozZGoJkRPevqw7flHraKK9PtjvoMiEs0w,37188
|
|
11
|
+
getfootballdata-0.1.0.dist-info/METADATA,sha256=EZS9J-ApYwJv2gwse_buqmHZxwxjrvU_iPRYPJvbK5w,5260
|
|
12
|
+
getfootballdata-0.1.0.dist-info/WHEEL,sha256=YVMoNqKzERt-wjUZwJ33xBGAwnFl-4cqbYkTtWa4itE,91
|
|
13
|
+
getfootballdata-0.1.0.dist-info/top_level.txt,sha256=vH3LQZS30zltBF8geUokep7WtnAV-ZDZDPPhQQHy0Wg,16
|
|
14
|
+
getfootballdata-0.1.0.dist-info/RECORD,,
|