Spaces:
Sleeping
Sleeping
Update src/streamlit_app.py
Browse files- src/streamlit_app.py +21 -16
src/streamlit_app.py
CHANGED
|
@@ -3,8 +3,10 @@ import requests
|
|
| 3 |
import pandas as pd
|
| 4 |
import io
|
| 5 |
import time
|
|
|
|
|
|
|
| 6 |
|
| 7 |
-
# Function to fetch WNBA player game log data
|
| 8 |
@st.cache_data
|
| 9 |
def fetch_wnba_data():
|
| 10 |
url = "https://stats.wnba.com/stats/playergamelogs"
|
|
@@ -33,14 +35,14 @@ def fetch_wnba_data():
|
|
| 33 |
"VsDivision": ""
|
| 34 |
}
|
| 35 |
headers = {
|
| 36 |
-
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/
|
| 37 |
"Accept": "application/json, text/plain, */*",
|
| 38 |
"x-nba-stats-origin": "stats",
|
| 39 |
"x-nba-stats-token": "true",
|
| 40 |
"Referer": "https://stats.wnba.com/players/boxscores-traditional/",
|
| 41 |
"Accept-Encoding": "gzip, deflate, br",
|
| 42 |
"Accept-Language": "en-GB,en-US;q=0.9,en;q=0.8",
|
| 43 |
-
"sec-ch-ua": '"
|
| 44 |
"sec-ch-ua-mobile": "?0",
|
| 45 |
"sec-ch-ua-platform": '"Windows"',
|
| 46 |
"sec-fetch-dest": "empty",
|
|
@@ -48,11 +50,18 @@ def fetch_wnba_data():
|
|
| 48 |
"sec-fetch-site": "same-origin"
|
| 49 |
}
|
| 50 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 51 |
try:
|
| 52 |
st.write("Sending API request...")
|
| 53 |
-
|
| 54 |
-
response.
|
| 55 |
-
|
|
|
|
|
|
|
| 56 |
data = response.json()
|
| 57 |
game_logs = data.get("resultSets", [])[0].get("rowSet", [])
|
| 58 |
if not game_logs:
|
|
@@ -60,13 +69,13 @@ def fetch_wnba_data():
|
|
| 60 |
return []
|
| 61 |
return game_logs
|
| 62 |
except requests.Timeout:
|
| 63 |
-
st.error("Request timed out after
|
| 64 |
return []
|
| 65 |
except requests.HTTPError as e:
|
| 66 |
-
st.error(f"HTTP error
|
| 67 |
return []
|
| 68 |
except requests.RequestException as e:
|
| 69 |
-
st.error(f"
|
| 70 |
return []
|
| 71 |
|
| 72 |
# Function to convert game logs to a DataFrame
|
|
@@ -95,11 +104,7 @@ st.title("WNBA 2025 Player Game Logs")
|
|
| 95 |
|
| 96 |
# Fetch data with progress feedback
|
| 97 |
with st.spinner("Fetching WNBA player game log data..."):
|
| 98 |
-
start_time = time.time()
|
| 99 |
game_logs = fetch_wnba_data()
|
| 100 |
-
fetch_time = time.time() - start_time
|
| 101 |
-
if game_logs:
|
| 102 |
-
st.success(f"Data fetched successfully in {fetch_time:.2f} seconds!")
|
| 103 |
|
| 104 |
if game_logs:
|
| 105 |
# Create DataFrame
|
|
@@ -123,13 +128,13 @@ if game_logs:
|
|
| 123 |
|
| 124 |
# Display first 1000 records
|
| 125 |
st.subheader("Game Log Data (First 1000 Records)")
|
| 126 |
-
display_df = filtered_df.iloc[:1000]
|
| 127 |
st.write(f"Displaying {len(display_df)} records (out of {len(filtered_df)} after filtering)")
|
| 128 |
st.dataframe(display_df, use_container_width=True)
|
| 129 |
|
| 130 |
# Download button for all records
|
| 131 |
st.subheader("Download Data")
|
| 132 |
-
csv_data = convert_to_csv(filtered_df)
|
| 133 |
st.download_button(
|
| 134 |
label=f"Download All {len(filtered_df)} Records as CSV",
|
| 135 |
data=csv_data,
|
|
@@ -137,7 +142,7 @@ if game_logs:
|
|
| 137 |
mime="text/csv"
|
| 138 |
)
|
| 139 |
|
| 140 |
-
# Visualization
|
| 141 |
if player_filter != "All":
|
| 142 |
st.subheader(f"Points Scored by {player_filter}")
|
| 143 |
player_data = filtered_df[["Game_Date", "PTS"]].copy()
|
|
|
|
| 3 |
import pandas as pd
|
| 4 |
import io
|
| 5 |
import time
|
| 6 |
+
from requests.adapters import HTTPAdapter
|
| 7 |
+
from urllib3.util.retry import Retry
|
| 8 |
|
| 9 |
+
# Function to fetch WNBA player game log data with retry logic
|
| 10 |
@st.cache_data
|
| 11 |
def fetch_wnba_data():
|
| 12 |
url = "https://stats.wnba.com/stats/playergamelogs"
|
|
|
|
| 35 |
"VsDivision": ""
|
| 36 |
}
|
| 37 |
headers = {
|
| 38 |
+
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36",
|
| 39 |
"Accept": "application/json, text/plain, */*",
|
| 40 |
"x-nba-stats-origin": "stats",
|
| 41 |
"x-nba-stats-token": "true",
|
| 42 |
"Referer": "https://stats.wnba.com/players/boxscores-traditional/",
|
| 43 |
"Accept-Encoding": "gzip, deflate, br",
|
| 44 |
"Accept-Language": "en-GB,en-US;q=0.9,en;q=0.8",
|
| 45 |
+
"sec-ch-ua": '"Not/A)Brand";v="99", "Google Chrome";v="126", "Chromium";v="126"',
|
| 46 |
"sec-ch-ua-mobile": "?0",
|
| 47 |
"sec-ch-ua-platform": '"Windows"',
|
| 48 |
"sec-fetch-dest": "empty",
|
|
|
|
| 50 |
"sec-fetch-site": "same-origin"
|
| 51 |
}
|
| 52 |
|
| 53 |
+
# Set up retry strategy
|
| 54 |
+
session = requests.Session()
|
| 55 |
+
retries = Retry(total=3, backoff_factor=1, status_forcelist=[429, 500, 502, 503, 504])
|
| 56 |
+
session.mount("https://", HTTPAdapter(max_retries=retries))
|
| 57 |
+
|
| 58 |
try:
|
| 59 |
st.write("Sending API request...")
|
| 60 |
+
start_time = time.time()
|
| 61 |
+
response = session.get(url, params=params, headers=headers, timeout=30)
|
| 62 |
+
response.raise_for_status()
|
| 63 |
+
fetch_time = time.time() - start_time
|
| 64 |
+
st.write(f"API request successful. Fetched in {fetch_time:.2f} seconds.")
|
| 65 |
data = response.json()
|
| 66 |
game_logs = data.get("resultSets", [])[0].get("rowSet", [])
|
| 67 |
if not game_logs:
|
|
|
|
| 69 |
return []
|
| 70 |
return game_logs
|
| 71 |
except requests.Timeout:
|
| 72 |
+
st.error("Request timed out after 30 seconds. The API may be slow, or your network is unstable. Try again later.")
|
| 73 |
return []
|
| 74 |
except requests.HTTPError as e:
|
| 75 |
+
st.error(f"HTTP error: {e}. Check if the API requires updated headers or cookies (e.g., cf_clearance).")
|
| 76 |
return []
|
| 77 |
except requests.RequestException as e:
|
| 78 |
+
st.error(f"Request failed: {e}. Possible API or network issue.")
|
| 79 |
return []
|
| 80 |
|
| 81 |
# Function to convert game logs to a DataFrame
|
|
|
|
| 104 |
|
| 105 |
# Fetch data with progress feedback
|
| 106 |
with st.spinner("Fetching WNBA player game log data..."):
|
|
|
|
| 107 |
game_logs = fetch_wnba_data()
|
|
|
|
|
|
|
|
|
|
| 108 |
|
| 109 |
if game_logs:
|
| 110 |
# Create DataFrame
|
|
|
|
| 128 |
|
| 129 |
# Display first 1000 records
|
| 130 |
st.subheader("Game Log Data (First 1000 Records)")
|
| 131 |
+
display_df = filtered_df.iloc[:1000]
|
| 132 |
st.write(f"Displaying {len(display_df)} records (out of {len(filtered_df)} after filtering)")
|
| 133 |
st.dataframe(display_df, use_container_width=True)
|
| 134 |
|
| 135 |
# Download button for all records
|
| 136 |
st.subheader("Download Data")
|
| 137 |
+
csv_data = convert_to_csv(filtered_df)
|
| 138 |
st.download_button(
|
| 139 |
label=f"Download All {len(filtered_df)} Records as CSV",
|
| 140 |
data=csv_data,
|
|
|
|
| 142 |
mime="text/csv"
|
| 143 |
)
|
| 144 |
|
| 145 |
+
# Visualization
|
| 146 |
if player_filter != "All":
|
| 147 |
st.subheader(f"Points Scored by {player_filter}")
|
| 148 |
player_data = filtered_df[["Game_Date", "PTS"]].copy()
|