4 Commits

Author SHA1 Message Date
Pc
9a007f504c Wins update 2025-06-04 19:56:32 +02:00
Pc
b5fdbb3230 Updating matches
Updating players stats(not finished)
Not tested
2025-06-04 19:50:18 +02:00
35db71b8cc feat: get sportsmen full name and birthday from id 2025-06-04 00:19:57 +02:00
bdfa31c8ea fix: check for id in simple_insert_one() to avoid breaking autoincrement 2025-06-03 21:46:59 +02:00
4 changed files with 171 additions and 5 deletions

View File

@@ -4,6 +4,7 @@ import json
import lewy_globals
import requests
import time
from sqlalchemy import func
def safe_traverse(obj: dict, path: list, default=None):
result = obj
@@ -16,6 +17,21 @@ def safe_traverse(obj: dict, path: list, default=None):
finally:
return result
def get_stat_value(stats: dict, stat_id: str, field: str = "value", default=None):
"""
Bezpiecznie pobiera wartość z pola 'value' lub 'type' dla danego stat_id w strukturze 'stats'.
:param stats: słownik ze statystykami
:param stat_id: ID statystyki jako string, np. "595"
:param field: 'value' lub 'type'
:param default: wartość domyślna zwracana, jeśli coś pójdzie nie tak
:return: wartość z pola lub default
"""
try:
return stats[stat_id][field]
except (KeyError, TypeError):
return default
class scraper:
headers = {
@@ -61,6 +77,34 @@ class scraper:
# return False
return self.__czy_x_istnieje("kluby", id_klubu=id_klubu)
def id_na_imie_nazwisko_urodziny(self, zewnetrzne_id_sportowca: str = "MVC8zHZD"):
"""
Scraper z dykty xD
Pobiera imiona, nazwiska i dni urodzin sportowców z zewnętrznego id.
Działa na słowo honoru.
:param zewnetrzne_id_sportowca: Zewnętrzne id sportowca
:type zewnetrzne_id_sportowca: str
"""
if len(zewnetrzne_id_sportowca) != 8:
raise ValueError("Zewnętrzne ID sportowca powinno być długości 8!")
r = requests.get(f'https://www.flashscore.pl/?r=4:{zewnetrzne_id_sportowca}')
page = r.text
name_start_pos = page.find("data-testid=\"wcl-scores-heading-02\">") + 36
name_end_pos = page.find("</", name_start_pos)
name = page[name_start_pos:name_end_pos].strip().split(' ')
# Tak wiem... można by było użyć beautifulsoup4, ale nie ma sensu dodawać nowych zależności dla tylko jednej metody.
birthday_start_pos_1 = page.find("data-testid=\"wcl-scores-simpleText-01\">", name_end_pos) + 39
birthday_start_pos_2 = page.find("data-testid=\"wcl-scores-simpleText-01\">", birthday_start_pos_1) + 39
birthday_start_pos_3 = page.find("data-testid=\"wcl-scores-simpleText-01\">", birthday_start_pos_2) + 39
birthday_start_pos = page.find("data-testid=\"wcl-scores-simpleText-01\">", birthday_start_pos_3) + 39
birthday_end_pos = page.find("</", birthday_start_pos) - 1
birthday = None if birthday_end_pos - birthday_start_pos > 20 else page[birthday_start_pos:birthday_end_pos].strip(" ()")
return name, birthday
def aktualizuj_dane_sportowca(self, zewnetrzne_id_sportowca: str = "MVC8zHZD"):
stop_scraping = False
matches_to_add = []
@@ -69,6 +113,7 @@ class scraper:
# Jeśli nie, dodaj go w podobny sposób, jak
# w sample_data_init() (w lewy_db.py).
page = 0
match_num = 0
while not stop_scraping:
@@ -113,8 +158,42 @@ class scraper:
# TODO: dodaj obiekt mecz do bazy (simple_insert_one(), simple_insert_many())
print(f"{c.OKCYAN}Nowy mecz ({match_num}){c.ENDC}: {match}")
self.db.simple_insert_one("mecze",
zewnetrzne_id_meczu= safe_traverse(match, ["eventId"], default=""),
data= safe_traverse(match, ["eventStartTime"], default=func.now()),
gospodarze_id= safe_traverse(match, ["homeParticipant3CharName"], default=0),
gospodarze= safe_traverse(match, ["homeParticipantName"], default=""),
goscie_id= safe_traverse(match, ["awayParticipant3CharName"], default=0),
goscie= safe_traverse(match, ["awayParticipantName"], default=""),
gosp_wynik= safe_traverse(match, ["homeScore"], default=0),
gosc_wynik= safe_traverse(match, ["awayScore"], default=0),
sezon= safe_traverse(match, ["tournamentSeason"], default=""),
nazwa_turnieju= safe_traverse(match, ["tournamentTitle"], default=""),
skrocona_nazwa_turnieju=safe_traverse(match, ["tournamentTemplateShortCode"], default=""),
flaga= safe_traverse(match, ["flagId"], default=0),
)
match_num += 1
stats=safe_traverse(match, ["stats"], default=""),
self.db.increment_fields("sportowcy",zewnetrzne_id_sportowca,
ostatni_mecz= safe_traverse(match, ["eventId"], default=0), #TODO: Zaktualizuj statystyki sportowca
ilosc_wystapien= safe_traverse(match, ["eventId"], default=0), #TODO: Zaktualizuj statystyki sportowca
minut_gry= get_stat_value(stats, "595"),
gier_sum= 1 if get_stat_value(stats, "595") > 0 else 0 ,
goli_sum= get_stat_value(stats, "596"),
asyst_sum= get_stat_value(stats, "541"),
interwencji_sum= safe_traverse(match, ["eventId"], default=0), #TODO: Zaktualizuj statystyki sportowca
nieobronionych_interwencji_sum= safe_traverse(match, ["eventId"], default=0), #TODO: Zaktualizuj statystyki sportowca
zoltych_kartek_sum= get_stat_value(stats, "599"),
czerwonych_kartek_sum= get_stat_value(stats, "600"),
wygranych_sum = 1 if safe_traverse(match, ["winLoseShort"], default=0) == "Z" else 0,
wynik_sum= safe_traverse(match, ["eventId"], default=0), #TODO: Zaktualizuj statystyki sportowca
meczow_do_wynikow_sum= safe_traverse(match, ["eventId"], default=0), #TODO: Zaktualizuj statystyki sportowca
)
# TODO: Zaktualizuj statystyki sportowca

View File

@@ -10,6 +10,18 @@ import traceback
global db
class c:
HEADER = '\033[95m'
OKBLUE = '\033[94m'
OKCYAN = '\033[96m'
OKGREEN = '\033[92m'
WARNING = '\033[93m'
FAIL = '\033[91m'
ENDC = '\033[0m'
BOLD = '\033[1m'
UNDERLINE = '\033[4m'
ENDL = '\n'
class baza():
# global sportowcy, trofea, sportowcy_w_meczach, statystyki_sportowcow, kluby, mecze
@@ -168,9 +180,9 @@ class baza():
try:
return_val = func(self, *args, **kwargs)
except:
print( "\033[91m"
print(f"{c.FAIL}"
f"Wystąpił błąd podczas wykonywania zapytania SQL:"
"\033[0m"
f"{c.ENDC}"
"\n"
f"{traceback.format_exc()}")
self.session.rollback()
@@ -263,6 +275,14 @@ class baza():
if not isinstance(entity_type, str):
entity_type = entity_type.__name__
if "id" in kwargs:
print(f"{c.FAIL}UWAGA!{c.ENDC}")
print(f"Próbujesz dodać obiekt do tabeli, który ma już identyfikator.\n"
f"To spowoduje problemy w przyszłości, gdy będziesz chciał dodać nowy obiekt do bazy bez ustawiania id na sztywno\n"
f"(id klucza głównego nie zostanie zaktualizowane w sekwencji, przez co baza będzie próbowała dodać obiekt z id już istniejącego rekordu!).\n"
f"Aby naprawić dodawanie z autoinkrementującym kluczem zobacz {c.WARNING}https://stackoverflow.com/a/8745101{c.ENDC}\n"
f"Zostałeś ostrzeżony!")
print(f"[{round(time.time())}] INSERT")
obj = self.entities[entity_type](**kwargs)
@@ -287,6 +307,72 @@ class baza():
return 0
#return 1
@exit_gracefully
def increment_fields(self, entity_type, record_id, **increments):
"""
Dodaje wartości do istniejących pól (np. goli_sum += 2).
Użycie:
increment_fields(ldb.statystyki_sportowcow, 123, goli_sum=2, asyst_sum=1)
"""
if not isinstance(entity_type, str):
entity_type = entity_type.__name__
if entity_type not in self.entities:
print(f"Nieznany typ encji: {entity_type}")
return -1
model_class = self.entities[entity_type]
print(f"[{round(time.time())}] INCREMENT")
record = self.session.get(model_class, record_id)
if not record:
print(f"Rekord z ID {record_id} nie istnieje w tabeli {entity_type}")
return -1
for key, increment_value in increments.items():
if hasattr(record, key):
current_value = getattr(record, key, 0)
setattr(record, key, current_value + increment_value)
else:
print(f"⚠️ Pole '{key}' nie istnieje w modelu '{entity_type}' pomijam.")
self.session.commit()
return 0
@exit_gracefully
def simple_update_one(self, entity_type, record_id, **kwargs):
"""
Użycie:
simple_update_one(ldb.kluby, "polska", pelna_nazwa="Nowa Nazwa", skrocona_nazwa="NN")
Aktualizuje pojedynczy rekord w bazie danych na podstawie ID.
"""
if not isinstance(entity_type, str):
entity_type = entity_type.__name__
if entity_type not in self.entities:
print(f"Nieznany typ encji: {entity_type}")
return -1
model_class = self.entities[entity_type]
print(f"[{round(time.time())}] UPDATE")
record = self.session.get(model_class, record_id)
if not record:
print(f"Rekord z ID {record_id} nie istnieje w tabeli {entity_type}")
return -1
for key, value in kwargs.items():
if hasattr(record, key):
setattr(record, key, value)
else:
print(f"⚠️ Pole '{key}' nie istnieje w modelu '{entity_type}' pomijam.")
self.session.commit()
return 0
@exit_gracefully
def sample_data_init(self, override_safety_check=False):
"""
@@ -368,4 +454,5 @@ class baza():
session.commit()
return 0
return 1

View File

@@ -1,4 +1,4 @@
from git import Repo # hash ostatniego commitu
#from git import Repo # hash ostatniego commitu
import os
import time
import toml

Binary file not shown.