Hide keyboard shortcuts

Hot-keys on this page

r m x p   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

1"""LICENSE 

2Copyright 2020 Hermann Krumrey <hermann@krumreyh.com> 

3 

4This file is part of betbot. 

5 

6betbot is free software: you can redistribute it and/or modify 

7it under the terms of the GNU General Public License as published by 

8the Free Software Foundation, either version 3 of the License, or 

9(at your option) any later version. 

10 

11betbot is distributed in the hope that it will be useful, 

12but WITHOUT ANY WARRANTY; without even the implied warranty of 

13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 

14GNU General Public License for more details. 

15 

16You should have received a copy of the GNU General Public License 

17along with betbot. If not, see <http://www.gnu.org/licenses/>. 

18LICENSE""" 

19 

20import os 

21import csv 

22from typing import Union, Dict, List, Tuple 

23 

24import requests 

25 

26 

27class FootballDataUk: 

28 """ 

29 Class that handles retrieving data from football-data.co.uk 

30 """ 

31 

32 def __init__(self, data_path: str): 

33 """ 

34 Initializes the object 

35 :param data_path: The path in which to store the data files 

36 """ 

37 self.data_path = data_path 

38 os.makedirs(data_path, exist_ok=True) 

39 

40 TEAM_MAP = { 

41 "Nurnberg": "FCN", 

42 "Mainz": "M05", 

43 "Leverkusen": "B04", 

44 "Dortmund": "BVB", 

45 "M'gladbach": "BMG", 

46 "Ein Frankfurt": "SGE", 

47 "Augsburg": "FCA", 

48 "Bayern Munich": "FCB", 

49 "Schalke 04": "S04", 

50 "Fortuna Dusseldorf": "F95", 

51 "Hannover": "H96", 

52 "Hertha": "BSC", 

53 "RB Leipzig": "RBL", 

54 "Freiburg": "SCF", 

55 "Hoffenheim": "TSG", 

56 "Stuttgart": "VFB", 

57 "Wolfsburg": "WOB", 

58 "Werder Bremen": "BRE", 

59 "Union Berlin": "FCU", 

60 "Paderborn": "SCP", 

61 "FC Koln": "KOE", 

62 "Bielefeld": "DSC", 

63 "Greuther Furth": "SGF", 

64 "Bochum": "BOC", 

65 "Heidenheim": "HDH", 

66 "Erzgebirge Aue": "AUE", 

67 "Hansa Rostock": "FCH", 

68 "Ingolstadt": "FCI", 

69 "St Pauli": "STP", 

70 "Hamburg": "HSV", 

71 "Holstein Kiel": "KIE", 

72 "Regensburg": "SSV", 

73 "Karlsruhe": "KSC", 

74 "Dresden": "SGD", 

75 "Darmstadt": "D98", 

76 "Sandhausen": "SVS", 

77 } 

78 

79 def download_history(self): 

80 """ 

81 Download history for the first and second bundesliga 

82 :return: None 

83 """ 

84 for year in range(2000, 2021): 

85 next_year = year + 1 

86 year_string = str(year)[-2:] + str(next_year)[-2:] 

87 for league in ["D1", "D2"]: 

88 path = os.path.join(self.data_path, f"{league}-{year}.csv") 

89 if os.path.isfile(path): 

90 continue 

91 url = f"https://www.football-data.co.uk/mmz4281/" \ 

92 f"{year_string}/{league}.csv" 

93 with open(path, "wb") as f: 

94 f.write(requests.get(url).content) 

95 

96 def get_history_matches(self) -> List[Dict[str, Union[str, int, float]]]: 

97 """ 

98 Retrieves data on historical bundesliga and bundesliga 2 matches 

99 :return: A list of match dictionaries 

100 """ 

101 matches = [] 

102 for history_file in [ 

103 os.path.join(self.data_path, x) 

104 for x in os.listdir(self.data_path) 

105 ]: 

106 matches += self.load_matches(history_file) 

107 return matches 

108 

109 def load_matches(self, data_file: str) -> \ 

110 List[Dict[str, Union[str, int, float]]]: 

111 """ 

112 Loads match data from a single CSV file 

113 :param data_file: The path to the CSV file 

114 :return: The match data 

115 """ 

116 matches: List[Dict[str, Union[str, int, float]]] = [] 

117 file_matches = self.load_history_file(data_file) 

118 for match in file_matches: 

119 home = self.TEAM_MAP.get(str(match["HomeTeam"])) 

120 away = self.TEAM_MAP.get(str(match["AwayTeam"])) 

121 if home is None or away is None: 

122 continue 

123 try: 

124 matches.append({ 

125 "home_team": home, 

126 "away_team": away, 

127 "home_score": int(match["FTHG"]), 

128 "away_score": int(match["FTAG"]), 

129 "home_odds": float(match["WHH"]), 

130 "away_odds": float(match["WHA"]), 

131 "draw_odds": float(match["WHD"]) 

132 }) 

133 except ValueError: 

134 continue 

135 return matches 

136 

137 @staticmethod 

138 def load_history_file(history_file: str) -> List[Dict[str, str]]: 

139 """ 

140 Loads the contents of a history file 

141 :param history_file: The history file to load 

142 :return: A list of match dictionaries 

143 """ 

144 with open(history_file, "r", encoding="latin1") as f: 

145 lines = [x for x in csv.reader(f)] 

146 header = lines.pop(0) 

147 data: List[Dict[str, str]] = [] 

148 for line in lines: 

149 item = {} 

150 for i, key in enumerate(header): 

151 if not key or i >= len(line): 

152 continue 

153 item[key] = line[i] 

154 data.append(item) 

155 return data 

156 

157 def get_odds(self) -> Dict[Tuple[str, str], Tuple[float, float, float]]: 

158 """ 

159 Loads currently available odds 

160 :return: The current odds (home, draw, away) mapped to home/away teams 

161 """ 

162 path = "/tmp/fixtures.csv" 

163 url = "https://www.football-data.co.uk/fixtures.csv" 

164 with open(path, "wb") as f: 

165 f.write(requests.get(url).content) 

166 

167 odds = {} 

168 for match in self.load_matches(path): 

169 match_tuple = (str(match["home_team"]), str(match["away_team"])) 

170 odds_tuple = ( 

171 float(match["home_odds"]), 

172 float(match["draw_odds"]), 

173 float(match["away_odds"]) 

174 ) 

175 odds[match_tuple] = odds_tuple 

176 return odds