Натхненний моїм попереднім проєктом, Gameday Notifications, я вирішив взятися за задачу створення бази даних гравців НБА, яку можна буде запитувати. Цей проєкт справжньо задовольнив мою пристрасть до спортивних даних і був дуже приємним у розробці.
Для реалізації цього проєкту я використав наступні інструменти:
S3: Amazon Web Services (AWS) S3 (Simple Storage Service) — це служба хмарного зберігання, яка дозволяє зберігати та отримувати великі обсяги даних з будь-якої точки в Інтернеті. Вона дуже гнучка і може використовуватись для таких задач, як резервне копіювання даних або хостинг вебсайтів.
AWS Glue: AWS Glue — це служба, яка допомагає підготувати і завантажити дані для аналізу. Вона автоматично знаходить та організовує ваші дані і трансформує їх за допомогою вбудованих інструментів. Це полегшує об'єднання даних з різних джерел для аналітичних потреб.
Amazon Athena: Amazon Athena — це служба, яка дозволяє запускати SQL запити на даних, що зберігаються в Amazon S3. Вона безсерверна, тому вам не потрібно керувати інфраструктурою, і ви сплачуєте тільки за виконані запити. Це спрощує аналіз великих наборів даних за допомогою SQL.
Prerequisites: Включено в цю папку проєкту є файл requirements.txt, який встановлює необхідні нестандартні модулі для запуску цієї програми.
boto3==1.26.137
python-dotenv==1.0.0
requests==2.28.2
Деталі реалізації:
Спочатку я створив файл .env, щоб я міг запускати цей скрипт безпосередньо в Visual Studio Code. Він містив такі змінні:
SPORTS_DATA_API_KEY="YOUR_API_KEY"
NBA_ENDPOINT=https://api.sportsdata.io/v3/nba/scores/json/PlayersActiveBasic
AWS_ACCESS_KEY_ID="YOUR_AWS_ACCESS_KEY"
AWS_SECRET_ACCESS_KEY="YOUR_AWS_SECRET_ACCESS_KEY"
AWS_DEFAULT_REGION=us-east-1
Переходячи до Python скрипта, я почав з імпорту необхідних модулів.
import boto3
import json
import time
import requests
from dotenv import load_dotenv
import os
Далі я визначив змінні, які будуть використовуватися в різних частинах коду.
region = "us-east-1" # Заміни на ваш регіон AWS
bucket_name = "sports-analytics-data-lake" # Заміни на унікальну назву S3 бакету
glue_database_name = "glue_nba_data_lake"
athena_output_location = f"s3://{bucket_name}/athena-results/"
Тепер перейдемо до налаштування S3 бакету:
def create_s3_bucket():
"""Створити S3 бакет для зберігання спортивних даних."""
try:
if region == "us-east-1":
s3_client.create_bucket(Bucket=bucket_name)
else:
s3_client.create_bucket(
Bucket=bucket_name,
CreateBucketConfiguration={"LocationConstraint": region},
)
print(f"S3 бакет '{bucket_name}' створений успішно.")
except Exception as e:
print(f"Помилка при створенні S3 бакету: {e}")
Цей скрипт досить простий. Важливо зауважити, що S3 бакет повинен мати унікальну назву по всьому світу, і якщо назва не унікальна, створення бакету не відбудеться.
Інша необхідна функція — це налаштування того, як дані будуть завантажуватися в S3 бакет. Важливо зауважити, що кожну дію необхідно визначити для того, щоб скрипт працював ефективно.
def upload_data_to_s3(data):
"""Завантажити дані НБА в S3 бакет."""
try:
# Перетворити дані в JSON з лінійними розділеннями
line_delimited_data = convert_to_line_delimited_json(data)
# Визначити ключ об'єкта S3
file_key = "raw-data/nba_player_data.jsonl"
# Завантажити JSON дані в S3
s3_client.put_object(
Bucket=bucket_name,
Key=file_key,
Body=line_delimited_data
)
print(f"Завантажено дані в S3: {file_key}")
except Exception as e:
print(f"Помилка при завантаженні даних в S3: {e}")
Коли функція створення S3 бакету завершена, наступним етапом йде налаштування бази даних AWS Glue.
Це дозволить зберігати дані організованими та чистими.
def create_glue_database():
"""Створити базу даних Glue для озера даних."""
try:
glue_client.create_database(
DatabaseInput={
"Name": glue_database_name,
"Description": "Glue база даних для спортивної аналітики НБА.",
}
)
print(f"База даних Glue '{glue_database_name}' успішно створена.")
except Exception as e:
print(f"Помилка при створенні бази даних Glue: {e}")
Після створення бази даних Glue необхідно створити таблицю Glue. Це визначить, як будуть впорядковуватися дані в базі даних.
def create_glue_table():
"""Створити таблицю Glue для даних."""
try:
glue_client.create_table(
DatabaseName=glue_database_name,
TableInput={
"Name": "nba_players",
"StorageDescriptor": {
"Columns": [
{"Name": "PlayerID", "Type": "int"},
{"Name": "FirstName", "Type": "string"},
{"Name": "LastName", "Type": "string"},
{"Name": "Team", "Type": "string"},
{"Name": "Position", "Type": "string"},
{"Name": "Points", "Type": "int"}
],
"Location": f"s3://{bucket_name}/raw-data/",
"InputFormat": "org.apache.hadoop.mapred.TextInputFormat",
"OutputFormat": "org.apache.hadoop.hive.ql.io.HiveIgnoreKeyTextOutputFormat",
"SerdeInfo": {
"SerializationLibrary": "org.openx.data.jsonserde.JsonSerDe"
},
},
"TableType": "EXTERNAL_TABLE",
},
)
print(f"Таблиця Glue 'nba_players' успішно створена.")
except Exception as e:
print(f"Помилка при створенні таблиці Glue: {e}")
Це призводить нас до останньої необхідної служби AWS для цього проєкту: Athena. Athena дозволяє запитувати дані, отримані з API. Один цікавий запит може бути сортування даних за рідним містом, щоб дізнатися, яке місто виробляє найвищоплачуваних гравців. Я знаю, що моє рідне місто, Сент-Луїс, буде добре представлено завдяки великим зарплатам Джейсона Татума та Бредлі Біла!
def configure_athena():
"""Налаштувати місце виведення Athena."""
try:
athena_client.start_query_execution(
QueryString="CREATE DATABASE IF NOT EXISTS nba_analytics",
QueryExecutionContext={"Database": glue_database_name},
ResultConfiguration={"OutputLocation": athena_output_location},
)
print("Місце виведення Athena успішно налаштоване.")
except Exception as e:
print(f"Помилка при налаштуванні Athena: {e}")
Тепер, коли всі необхідні компоненти AWS визначені, наступним етапом буде налаштування виклику API. Для цього знадобиться API-ключ, який був збережений окремо у файлі .env.
def fetch_nba_data():
"""Отримати дані про гравців НБА з sportsdata.io."""
try:
headers = {"Ocp-Apim-Subscription-Key": api_key}
response = requests.get(nba_endpoint, headers=headers)
response.raise_for_status() # Підняти помилку при поганих кодах статусу
print("Дані НБА успішно отримано.")
return response.json() # Повернути JSON відповідь
except Exception as e:
print(f"Помилка при отриманні даних НБА: {e}")
return []
Щойно отримані дані потрібно буде конвертувати для таблиці Glue.
Це досягається за допомогою функції json.dmps() в модулі json, який входить до стандартної бібліотеки Python.
def convert_to_line_delimited_json(data):
"""Конвертувати дані в формат JSON з лінійними розділеннями."""
print("Конвертація даних у формат JSON з лінійними розділеннями...")
return "\n".join([json.dumps(record) for record in data])
Нарешті, основний робочий процес налаштовується відповідно до стандарту if name == "main", як це передбачено кращими практиками Python.
def main():
print("Налаштовуємо озеро даних для спортивної аналітики НБА...")
create_s3_bucket()
time.sleep(5) # Переконайтесь, що створення бакету успішно завершилось
create_glue_database()
nba_data = fetch_nba_data()
if nba_data: # Продовжити, якщо дані були отримані успішно
upload_data_to_s3(nba_data)
create_glue_table()
configure_athena()
print("Налаштування озера даних завершено.")
if __name__ == "__main__":
main()
Основні висновки:
• Цей проєкт поглибив моє розуміння служб AWS і того, як ефективно обробляти та аналізувати великі набори даних. Одна з ключових відмінностей від Microsoft Azure — це можливість викликати всі служби AWS просто за допомогою імпорту boto3. Це справжня зміна правил гри та робить написання Інфраструктури як коду для AWS на Python набагато простішим, ніж для Microsoft. Якщо чесно, я здається починаю закохуватись у AWS!
Висновок:
• NBA Data Pipeline — потужний приклад використання хмарних технологій для спортивної аналітики. Перегляньте повний проєкт на GitHub.
Перекладено з: Building an NBA Data Pipeline: A Scalable Data Solution for NBA Analytics with AWS