irongit

An AI project that includes a scraper for NFL data, postgres database, and user interface. It uses a classification algorithm to predict winners.

308 lines11 KB
1{
2 "cells": [
3 {
4 "cell_type": "markdown",
5 "metadata": {},
6 "source": [
7 "## 1. Set up the scraper\n",
8 "* Download data from nfl.com\n",
9 "* Use internal api with Bearer Key"
10 ]
11 },
12 {
13 "cell_type": "markdown",
14 "metadata": {},
15 "source": [
16 "### 1.1 Get a working example for Bearer token"
17 ]
18 },
19 {
20 "cell_type": "code",
21 "execution_count": 2,
22 "metadata": {},
23 "outputs": [],
24 "source": [
25 "import time\n",
26 "from browsermobproxy import Server\n",
27 "from selenium import webdriver\n",
28 "import json\n",
29 "import os\n",
30 "BMP_PATH = os.path.abspath('browsermob-proxy-2.1.4/bin/browsermob-proxy.bat')\n",
31 "\n",
32 "# Start BrowserMob Proxy\n",
33 "server = Server(BMP_PATH)\n",
34 "server.start()\n",
35 "proxy = server.create_proxy()\n",
36 "\n",
37 "# Configure Chrome with the proxy\n",
38 "chrome_options = webdriver.ChromeOptions()\n",
39 "chrome_options.add_argument(f'--proxy-server={proxy.proxy}')\n",
40 "chrome_options.add_argument('--ignore-certificate-errors')\n",
41 "chrome_options.add_argument('--headless')\n",
42 "driver = webdriver.Chrome(options=chrome_options)\n",
43 "# Navigate to the website\n",
44 "driver.get(\"https://nfl.com/scores\")\n",
45 "\n",
46 "# Start capturing network traffic\n",
47 "proxy.new_har(\"nfl\", options={'captureHeaders': True})\n",
48 "\n",
49 "# Wait for the header with the name \"Authorization\"\n",
50 "timeout = 60 # Adjust the timeout as needed\n",
51 "def get_auth_token():\n",
52 " start_time = time.time()\n",
53 " while time.time() - start_time < timeout:\n",
54 " har = proxy.har\n",
55 " for entry in har['log']['entries']:\n",
56 " request_headers = entry['request']['headers']\n",
57 " for header in request_headers:\n",
58 " if header['name'] == 'Authorization':\n",
59 " return header['value']\n",
60 " time.sleep(1)\n",
61 " return None\n",
62 "auth_token = get_auth_token()\n",
63 "\n",
64 "# Store the auth token\n",
65 "auth_path = 'auth.json'\n",
66 "auth_json = {\n",
67 " 'time': time.time(),\n",
68 " 'token': auth_token\n",
69 "}\n",
70 "with open(auth_path, 'w') as f:\n",
71 " json.dump(auth_json, f)\n",
72 "\n",
73 "# Stop capturing network traffic\n",
74 "har = proxy.har\n",
75 "\n",
76 "# Close the browser and BrowserMob Proxy\n",
77 "driver.quit()\n",
78 "server.stop()"
79 ]
80 },
81 {
82 "cell_type": "markdown",
83 "metadata": {},
84 "source": [
85 "### 1.2 Create a class that manages requests to nfl.com"
86 ]
87 },
88 {
89 "cell_type": "code",
90 "execution_count": 5,
91 "metadata": {},
92 "outputs": [],
93 "source": [
94 "from nfl_client import NFLClient\n",
95 "client = NFLClient(headless=True)"
96 ]
97 },
98 {
99 "cell_type": "code",
100 "execution_count": 7,
101 "metadata": {},
102 "outputs": [
103 {
104 "name": "stdout",
105 "output_type": "stream",
106 "text": [
107 "Auth Token: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJjbGllbnRJZCI6ImU1MzVjN2MwLTgxN2YtNDc3Ni04OTkwLTU2NTU2ZjhiMTkyOCIsImNsaWVudEtleSI6IjRjRlVXNkRtd0pwelQ5TDdMckczcVJBY0FCRzVzMDRnIiwiaXNzIjoiTkZMIiwiZGV2aWNlSWQiOiI0YTIzZGM2My00YmQ2LTQ0OTMtYWVmNC0yNDk0OGRkNGMxYTUiLCJwbGFucyI6W3sicGxhbiI6ImZyZWUiLCJleHBpcmF0aW9uRGF0ZSI6IjIwMjQtMTEtMDQiLCJzb3VyY2UiOiJORkwiLCJzdGFydERhdGUiOiIyMDIzLTExLTA1Iiwic3RhdHVzIjoiQUNUSVZFIiwidHJpYWwiOmZhbHNlfV0sIkRpc3BsYXlOYW1lIjoiV0VCX0RFU0tUT1BfREVTS1RPUCIsIk5vdGVzIjoiIiwiZm9ybUZhY3RvciI6IkRFU0tUT1AiLCJsdXJhQXBwS2V5IjoiU1pzNTdkQkdSeGJMNzI4bFZwN0RZUSIsInBsYXRmb3JtIjoiREVTS1RPUCIsInByb2R1Y3ROYW1lIjoiV0VCIiwiY2l0eSI6ImFwcGxlIHZhbGxleSIsImNvdW50cnlDb2RlIjoiVVMiLCJkbWFDb2RlIjoiODAzIiwiaG1hVGVhbXMiOlsiMTA0MDI1MTAtODkzMS0wZDVmLTk4MTUtNzliYjc5NjQ5YTY1IiwiMTA0MDI1MjAtOTZiZi1lOWYyLTRmNjgtODUyMWNhODk2MDYwIiwiMTA0MDQ0MDAtM2IzNS0wNzNmLTE5N2UtMTk0YmI4MjQwNzIzIl0sInJlZ2lvbiI6IkNBIiwiYnJvd3NlciI6IkNocm9tZSBIZWFkbGVzcyIsImNlbGx1bGFyIjpmYWxzZSwiZW52aXJvbm1lbnQiOiJwcm9kdWN0aW9uIiwicm9sZXMiOlsiZnJlZSJdLCJleHAiOjE2OTkxNjQ3MTh9.l60UboGxeZ4ma5dfBircoc9ok_X25aerWyTFFxYTJjo\n"
108 ]
109 }
110 ],
111 "source": [
112 "client.load_auth_token(store_har=True)\n",
113 "print('Auth Token:', client.auth_token)"
114 ]
115 },
116 {
117 "cell_type": "markdown",
118 "metadata": {},
119 "source": [
120 "### 1.3 Convert har entry into json"
121 ]
122 },
123 {
124 "cell_type": "code",
125 "execution_count": 4,
126 "metadata": {},
127 "outputs": [
128 {
129 "data": {
130 "text/plain": [
131 "{'/football/v2/games/{id}': {'query_parameters': {'withExternalIds': {'type': 'boolean',\n",
132 " 'example': 'true'}},\n",
133 " 'path_parameters': {'id': {'type': 'string',\n",
134 " 'example': 'b07eaa67-f053-11ed-b4a7-bab79e4492fa'}},\n",
135 " 'response_sample': {'id': 'b07eaa67-f053-11ed-b4a7-bab79e4492fa',\n",
136 " 'homeTeam': {'id': '10402310-a47e-10ea-7442-16b633633637',\n",
137 " 'currentLogo': 'https://static.www.nfl.com/{formatInstructions}/league/api/clubs/logos/KC',\n",
138 " 'fullName': 'Kansas City Chiefs'},\n",
139 " 'awayTeam': {'id': '10402700-1662-d8ad-f45c-0b0ea460d045',\n",
140 " 'currentLogo': 'https://static.www.nfl.com/{formatInstructions}/league/api/clubs/logos/MIA',\n",
141 " 'fullName': 'Miami Dolphins'},\n",
142 " 'category': None,\n",
143 " 'date': '2023-11-05',\n",
144 " 'time': '2023-11-05T14:30:00Z',\n",
145 " 'broadcastInfo': {'homeNetworkChannels': ['NFL NETWORK'],\n",
146 " 'awayNetworkChannels': ['NFL NETWORK'],\n",
147 " 'internationalWatchOptions': [{'countryCode': 'CA',\n",
148 " 'broadcasters': ['DAZN Canada', 'RDS', 'TSN']},\n",
149 " {'countryCode': 'GB',\n",
150 " 'broadcasters': ['Sky Sports', 'NFL Game Pass on DAZN']},\n",
151 " {'countryCode': 'MX', 'broadcasters': ['NFL Game Pass on DAZN']},\n",
152 " {'countryCode': 'DE',\n",
153 " 'broadcasters': ['NFL Game Pass on DAZN', 'DAZN Germany (OTT)', 'RTL']},\n",
154 " {'countryCode': 'AU',\n",
155 " 'broadcasters': ['NFL Game Pass on DAZN', 'ESPN', 'TVNZ+']},\n",
156 " {'countryCode': 'FR',\n",
157 " 'broadcasters': ['NFL Game Pass on DAZN', 'beIN 2', '6Play']},\n",
158 " {'countryCode': 'BR',\n",
159 " 'broadcasters': ['NFL Game Pass on DAZN', 'ESPN2']}],\n",
160 " 'territory': 'NATIONAL'},\n",
161 " 'neutralSite': None,\n",
162 " 'venue': {'id': '00082031-5500-35b5-a67a-7f374ebf7168',\n",
163 " 'name': 'Frankfurt Stadium'},\n",
164 " 'season': 2023,\n",
165 " 'seasonType': 'REG',\n",
166 " 'status': 'SCHEDULED',\n",
167 " 'week': 9,\n",
168 " 'weekType': 'REG',\n",
169 " 'externalIds': [{'source': 'elias', 'id': '2023110500'},\n",
170 " {'source': 'gsis', 'id': '59296'},\n",
171 " {'source': 'slug', 'id': 'dolphins-at-chiefs-2023-reg-9'}],\n",
172 " 'ticketUrl': None,\n",
173 " 'ticketVendors': []}}}"
174 ]
175 },
176 "execution_count": 4,
177 "metadata": {},
178 "output_type": "execute_result"
179 }
180 ],
181 "source": [
182 "from nfl_client.url_utils import har_entry_parse\n",
183 "import json\n",
184 "with open('nfl_client_data/sample_har_entry.json', 'r') as f:\n",
185 " data = json.load(f)\n",
186 "\n",
187 "url_data = har_entry_parse(data)\n",
188 "url_data"
189 ]
190 },
191 {
192 "cell_type": "markdown",
193 "metadata": {},
194 "source": [
195 "#### 1.3.1 Create something to convert this into openapi"
196 ]
197 },
198 {
199 "cell_type": "code",
200 "execution_count": 5,
201 "metadata": {},
202 "outputs": [
203 {
204 "name": "stdout",
205 "output_type": "stream",
206 "text": [
207 "{'/football/v2/games/{id}': {'query_parameters': {'withExternalIds': {'type': 'boolean', 'example': 'true'}}, 'path_parameters': {'id': {'type': 'string', 'example': 'b07eaa67-f053-11ed-b4a7-bab79e4492fa'}}, 'response_sample': {'id': 'b07eaa67-f053-11ed-b4a7-bab79e4492fa', 'homeTeam': {'id': '10402310-a47e-10ea-7442-16b633633637', 'currentLogo': 'https://static.www.nfl.com/{formatInstructions}/league/api/clubs/logos/KC', 'fullName': 'Kansas City Chiefs'}, 'awayTeam': {'id': '10402700-1662-d8ad-f45c-0b0ea460d045', 'currentLogo': 'https://static.www.nfl.com/{formatInstructions}/league/api/clubs/logos/MIA', 'fullName': 'Miami Dolphins'}, 'category': None, 'date': '2023-11-05', 'time': '2023-11-05T14:30:00Z', 'broadcastInfo': {'homeNetworkChannels': ['NFL NETWORK'], 'awayNetworkChannels': ['NFL NETWORK'], 'internationalWatchOptions': [{'countryCode': 'CA', 'broadcasters': ['DAZN Canada', 'RDS', 'TSN']}, {'countryCode': 'GB', 'broadcasters': ['Sky Sports', 'NFL Game Pass on DAZN']}, {'countryCode': 'MX', 'broadcasters': ['NFL Game Pass on DAZN']}, {'countryCode': 'DE', 'broadcasters': ['NFL Game Pass on DAZN', 'DAZN Germany (OTT)', 'RTL']}, {'countryCode': 'AU', 'broadcasters': ['NFL Game Pass on DAZN', 'ESPN', 'TVNZ+']}, {'countryCode': 'FR', 'broadcasters': ['NFL Game Pass on DAZN', 'beIN 2', '6Play']}, {'countryCode': 'BR', 'broadcasters': ['NFL Game Pass on DAZN', 'ESPN2']}], 'territory': 'NATIONAL'}, 'neutralSite': None, 'venue': {'id': '00082031-5500-35b5-a67a-7f374ebf7168', 'name': 'Frankfurt Stadium'}, 'season': 2023, 'seasonType': 'REG', 'status': 'SCHEDULED', 'week': 9, 'weekType': 'REG', 'externalIds': [{'source': 'elias', 'id': '2023110500'}, {'source': 'gsis', 'id': '59296'}, {'source': 'slug', 'id': 'dolphins-at-chiefs-2023-reg-9'}], 'ticketUrl': None, 'ticketVendors': []}}}\n"
208 ]
209 }
210 ],
211 "source": [
212 "from nfl_client.url_utils import generate_openapi_spec\n",
213 "\n",
214 "# Example\n",
215 "print(url_data)\n",
216 "openapi_yaml = generate_openapi_spec(url_data)\n",
217 "with open('openapi.yaml', 'w') as f:\n",
218 " f.write(openapi_yaml)"
219 ]
220 },
221 {
222 "cell_type": "markdown",
223 "metadata": {},
224 "source": [
225 "#### 1.3.2 Put it all together"
226 ]
227 },
228 {
229 "cell_type": "code",
230 "execution_count": 4,
231 "metadata": {},
232 "outputs": [
233 {
234 "data": {
235 "text/plain": [
236 "12"
237 ]
238 },
239 "execution_count": 4,
240 "metadata": {},
241 "output_type": "execute_result"
242 }
243 ],
244 "source": [
245 "from nfl_client import NFLClient\n",
246 "client = NFLClient()\n",
247 "url_json = client.download_endpoints(wait_time=300)\n",
248 "len(url_json)"
249 ]
250 },
251 {
252 "cell_type": "markdown",
253 "metadata": {},
254 "source": [
255 "### 1.2 Get team data through the teams endpoint"
256 ]
257 },
258 {
259 "cell_type": "code",
260 "execution_count": 35,
261 "metadata": {},
262 "outputs": [
263 {
264 "data": {
265 "text/plain": [
266 "<Response [200]>"
267 ]
268 },
269 "execution_count": 35,
270 "metadata": {},
271 "output_type": "execute_result"
272 }
273 ],
274 "source": [
275 "api_url = 'https://api.nfl.com/football/v2/teams?limit=100&season=2023'\n",
276 "request(api_url)"
277 ]
278 },
279 {
280 "cell_type": "code",
281 "execution_count": null,
282 "metadata": {},
283 "outputs": [],
284 "source": []
285 }
286 ],
287 "metadata": {
288 "kernelspec": {
289 "display_name": "Python 3",
290 "language": "python",
291 "name": "python3"
292 },
293 "language_info": {
294 "codemirror_mode": {
295 "name": "ipython",
296 "version": 3
297 },
298 "file_extension": ".py",
299 "mimetype": "text/x-python",
300 "name": "python",
301 "nbconvert_exporter": "python",
302 "pygments_lexer": "ipython3",
303 "version": "3.10.9"
304 }
305 },
306 "nbformat": 4,
307 "nbformat_minor": 2
308}