sportsball 0.10.12__tar.gz → 0.10.13__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {sportsball-0.10.12/sportsball.egg-info → sportsball-0.10.13}/PKG-INFO +2 -2
- {sportsball-0.10.12 → sportsball-0.10.13}/requirements.txt +1 -1
- {sportsball-0.10.12 → sportsball-0.10.13}/setup.py +1 -1
- {sportsball-0.10.12 → sportsball-0.10.13}/sportsball/__init__.py +1 -1
- {sportsball-0.10.12 → sportsball-0.10.13}/sportsball/data/afl/afl/afl_afl_league_model.py +20 -10
- {sportsball-0.10.12 → sportsball-0.10.13}/sportsball/data/afl/afltables/afl_afltables_league_model.py +24 -18
- {sportsball-0.10.12 → sportsball-0.10.13}/sportsball/data/aussportsbetting/aussportsbetting_league_model.py +21 -15
- {sportsball-0.10.12 → sportsball-0.10.13}/sportsball/data/espn/espn_league_model.py +40 -30
- {sportsball-0.10.12 → sportsball-0.10.13}/sportsball/data/google/google_address_model.py +10 -0
- sportsball-0.10.13/sportsball/data/hkjc/hkjc/hkjc_hkjc_league_model.py +111 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/sportsball/data/league_model.py +2 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/sportsball/data/nba/nba/nba_nba_league_model.py +28 -22
- sportsball-0.10.13/sportsball/data/nba/nbacom/nba_nbacom_league_model.py +46 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/sportsball/data/oddsportal/oddsportal_league_model.py +10 -4
- {sportsball-0.10.12 → sportsball-0.10.13}/sportsball/data/sportsdb/sportsdb_league_model.py +57 -49
- {sportsball-0.10.12 → sportsball-0.10.13}/sportsball/data/sportsreference/sportsreference_league_model.py +37 -31
- {sportsball-0.10.12 → sportsball-0.10.13/sportsball.egg-info}/PKG-INFO +2 -2
- {sportsball-0.10.12 → sportsball-0.10.13}/sportsball.egg-info/requires.txt +1 -1
- sportsball-0.10.12/sportsball/data/hkjc/hkjc/hkjc_hkjc_league_model.py +0 -104
- sportsball-0.10.12/sportsball/data/nba/nbacom/nba_nbacom_league_model.py +0 -40
- {sportsball-0.10.12 → sportsball-0.10.13}/LICENSE +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/MANIFEST.in +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/README.md +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/setup.cfg +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/sportsball/__main__.py +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/sportsball/args.py +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/sportsball/cache.py +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/sportsball/data/__init__.py +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/sportsball/data/address_model.py +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/sportsball/data/afl/__init__.py +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/sportsball/data/afl/afl/__init__.py +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/sportsball/data/afl/afl/afl_afl_bookie_model.py +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/sportsball/data/afl/afl/afl_afl_game_model.py +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/sportsball/data/afl/afl/afl_afl_odds_model.py +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/sportsball/data/afl/afl/afl_afl_player_model.py +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/sportsball/data/afl/afl/afl_afl_team_model.py +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/sportsball/data/afl/afl/afl_afl_venue_model.py +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/sportsball/data/afl/afltables/__init__.py +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/sportsball/data/afl/afltables/afl_afltables_coach_model.py +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/sportsball/data/afl/afltables/afl_afltables_game_model.py +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/sportsball/data/afl/afltables/afl_afltables_player_model.py +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/sportsball/data/afl/afltables/afl_afltables_team_model.py +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/sportsball/data/afl/afltables/afl_afltables_venue_model.py +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/sportsball/data/afl/aussportsbetting/__init__.py +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/sportsball/data/afl/aussportsbetting/afl_aussportsbetting_league_model.py +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/sportsball/data/afl/combined/__init__.py +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/sportsball/data/afl/combined/afl_combined_league_model.py +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/sportsball/data/afl/espn/__init__.py +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/sportsball/data/afl/espn/afl_espn_league_model.py +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/sportsball/data/afl/oddsportal/__init__.py +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/sportsball/data/afl/oddsportal/afl_oddsportal_league_model.py +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/sportsball/data/afl/position.py +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/sportsball/data/aussportsbetting/__init__.py +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/sportsball/data/aussportsbetting/aussportsbetting_bookie_model.py +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/sportsball/data/aussportsbetting/aussportsbetting_game_model.py +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/sportsball/data/aussportsbetting/aussportsbetting_odds_model.py +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/sportsball/data/aussportsbetting/aussportsbetting_team_model.py +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/sportsball/data/aussportsbetting/aussportsbetting_venue_model.py +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/sportsball/data/bet.py +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/sportsball/data/bookie_model.py +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/sportsball/data/coach_model.py +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/sportsball/data/combined/__init__.py +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/sportsball/data/combined/combined_address_model.py +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/sportsball/data/combined/combined_coach_model.py +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/sportsball/data/combined/combined_game_model.py +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/sportsball/data/combined/combined_league_model.py +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/sportsball/data/combined/combined_player_model.py +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/sportsball/data/combined/combined_team_model.py +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/sportsball/data/combined/combined_venue_model.py +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/sportsball/data/combined/combined_weather_model.py +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/sportsball/data/combined/ffill.py +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/sportsball/data/combined/most_interesting.py +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/sportsball/data/combined/null_check.py +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/sportsball/data/delimiter.py +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/sportsball/data/dividend_model.py +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/sportsball/data/espn/__init__.py +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/sportsball/data/espn/espn_bookie_model.py +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/sportsball/data/espn/espn_coach_model.py +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/sportsball/data/espn/espn_game_model.py +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/sportsball/data/espn/espn_odds_model.py +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/sportsball/data/espn/espn_player_model.py +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/sportsball/data/espn/espn_team_model.py +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/sportsball/data/espn/espn_venue_model.py +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/sportsball/data/field_type.py +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/sportsball/data/game_model.py +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/sportsball/data/google/__init__.py +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/sportsball/data/google/google_news_model.py +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/sportsball/data/hkjc/__init__.py +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/sportsball/data/hkjc/hkjc/__init__.py +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/sportsball/data/hkjc/hkjc/hkjc_hkjc_bookie_model.py +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/sportsball/data/hkjc/hkjc/hkjc_hkjc_coach_model.py +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/sportsball/data/hkjc/hkjc/hkjc_hkjc_dividend_model.py +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/sportsball/data/hkjc/hkjc/hkjc_hkjc_game_model.py +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/sportsball/data/hkjc/hkjc/hkjc_hkjc_odds_model.py +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/sportsball/data/hkjc/hkjc/hkjc_hkjc_owner_model.py +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/sportsball/data/hkjc/hkjc/hkjc_hkjc_player_model.py +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/sportsball/data/hkjc/hkjc/hkjc_hkjc_team_model.py +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/sportsball/data/hkjc/hkjc/hkjc_hkjc_venue_model.py +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/sportsball/data/hkjc/position.py +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/sportsball/data/league.py +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/sportsball/data/model.py +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/sportsball/data/nba/__init__.py +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/sportsball/data/nba/combined/__init__.py +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/sportsball/data/nba/combined/nba_combined_league_model.py +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/sportsball/data/nba/espn/__init__.py +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/sportsball/data/nba/espn/nba_espn_league_model.py +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/sportsball/data/nba/nba/__init__.py +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/sportsball/data/nba/nba/nba_nba_game_model.py +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/sportsball/data/nba/nba/nba_nba_team_model.py +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/sportsball/data/nba/nbacom/__init__.py +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/sportsball/data/nba/nbacom/nba_nbacom_game_model.py +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/sportsball/data/nba/nbacom/nba_nbacom_player_model.py +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/sportsball/data/nba/nbacom/nba_nbacom_team_model.py +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/sportsball/data/nba/nbacom/nba_nbacom_venue_model.py +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/sportsball/data/nba/oddsportal/__init__.py +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/sportsball/data/nba/oddsportal/nba_oddsportal_league_model.py +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/sportsball/data/nba/position.py +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/sportsball/data/nba/sportsdb/__init__.py +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/sportsball/data/nba/sportsdb/nba_sportsdb_league_model.py +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/sportsball/data/nba/sportsreference/__init__.py +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/sportsball/data/nba/sportsreference/nba_sportsreference_league_model.py +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/sportsball/data/ncaab/__init__.py +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/sportsball/data/ncaab/combined/__init__.py +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/sportsball/data/ncaab/combined/ncaab_combined_league_model.py +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/sportsball/data/ncaab/espn/__init__.py +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/sportsball/data/ncaab/espn/ncaab_espn_league_model.py +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/sportsball/data/ncaab/oddsportal/__init__.py +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/sportsball/data/ncaab/oddsportal/ncaab_oddsportal_league_model.py +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/sportsball/data/ncaab/sportsdb/__init__.py +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/sportsball/data/ncaab/sportsdb/ncaab_sportsdb_league_model.py +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/sportsball/data/ncaab/sportsreference/__init__.py +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/sportsball/data/ncaab/sportsreference/ncaab_sportsreference_league_model.py +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/sportsball/data/ncaaf/__init__.py +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/sportsball/data/ncaaf/combined/__init__.py +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/sportsball/data/ncaaf/combined/ncaaf_combined_league_model.py +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/sportsball/data/ncaaf/espn/__init__.py +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/sportsball/data/ncaaf/espn/ncaaf_espn_league_model.py +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/sportsball/data/ncaaf/oddsportal/__init__.py +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/sportsball/data/ncaaf/oddsportal/ncaaf_oddsportal_league_model.py +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/sportsball/data/ncaaf/sportsdb/__init__.py +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/sportsball/data/ncaaf/sportsdb/ncaaf_sportsdb_league_model.py +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/sportsball/data/ncaaf/sportsreference/__init__.py +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/sportsball/data/ncaaf/sportsreference/ncaaf_sportsreference_league_model.py +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/sportsball/data/news_model.py +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/sportsball/data/nfl/__init__.py +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/sportsball/data/nfl/aussportsbetting/__init__.py +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/sportsball/data/nfl/aussportsbetting/nfl_aussportsbetting_league_model.py +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/sportsball/data/nfl/combined/__init__.py +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/sportsball/data/nfl/combined/nfl_combined_league_model.py +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/sportsball/data/nfl/espn/__init__.py +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/sportsball/data/nfl/espn/nfl_espn_league_model.py +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/sportsball/data/nfl/oddsportal/__init__.py +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/sportsball/data/nfl/oddsportal/nfl_oddsportal_league_model.py +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/sportsball/data/nfl/position.py +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/sportsball/data/nfl/sportsdb/__init__.py +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/sportsball/data/nfl/sportsdb/nfl_sportsdb_league_model.py +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/sportsball/data/nfl/sportsreference/__init__.py +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/sportsball/data/nfl/sportsreference/nfl_sportsreference_league_model.py +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/sportsball/data/nhl/__init__.py +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/sportsball/data/nhl/combined/__init__.py +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/sportsball/data/nhl/combined/nhl_combined_league_model.py +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/sportsball/data/nhl/espn/__init__.py +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/sportsball/data/nhl/espn/nhl_espn_league_model.py +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/sportsball/data/nhl/oddsportal/__init__.py +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/sportsball/data/nhl/oddsportal/nhl_oddsportal_league_model.py +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/sportsball/data/nhl/position.py +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/sportsball/data/nhl/sportsdb/__init__.py +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/sportsball/data/nhl/sportsdb/nhl_sportsdb_league_model.py +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/sportsball/data/nhl/sportsreference/__init__.py +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/sportsball/data/nhl/sportsreference/nhl_sportsreference_league_model.py +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/sportsball/data/odds_model.py +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/sportsball/data/oddsportal/__init__.py +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/sportsball/data/oddsportal/decrypt.py +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/sportsball/data/oddsportal/oddsportal_bookie_model.py +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/sportsball/data/oddsportal/oddsportal_game_model.py +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/sportsball/data/oddsportal/oddsportal_odds_model.py +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/sportsball/data/oddsportal/oddsportal_team_model.py +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/sportsball/data/oddsportal/oddsportal_venue_model.py +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/sportsball/data/owner_model.py +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/sportsball/data/player_model.py +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/sportsball/data/season_type.py +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/sportsball/data/sex.py +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/sportsball/data/social_model.py +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/sportsball/data/species.py +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/sportsball/data/sportsdb/__init__.py +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/sportsball/data/sportsdb/sportsdb_game_model.py +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/sportsball/data/sportsdb/sportsdb_team_model.py +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/sportsball/data/sportsdb/sportsdb_venue_model.py +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/sportsball/data/sportsreference/__init__.py +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/sportsball/data/sportsreference/sportsreference_coach_model.py +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/sportsball/data/sportsreference/sportsreference_game_model.py +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/sportsball/data/sportsreference/sportsreference_player_model.py +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/sportsball/data/sportsreference/sportsreference_team_model.py +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/sportsball/data/sportsreference/sportsreference_venue_model.py +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/sportsball/data/team_model.py +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/sportsball/data/venue_model.py +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/sportsball/data/weather/__init__.py +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/sportsball/data/weather/gribstream/__init__.py +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/sportsball/data/weather/gribstream/gribstream_weather_model.py +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/sportsball/data/weather/multi_weather_model.py +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/sportsball/data/weather/openmeteo/__init__.py +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/sportsball/data/weather/openmeteo/openmeteo_weather_model.py +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/sportsball/data/weather_model.py +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/sportsball/data/wikipedia/__init__.py +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/sportsball/data/wikipedia/wikipedia_venue_model.py +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/sportsball/data/x/__init__.py +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/sportsball/data/x/x_social_model.py +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/sportsball/logger.py +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/sportsball/loglevel.py +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/sportsball/playwright.py +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/sportsball/sportsball.py +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/sportsball/vendor/__init__.py +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/sportsball/vendor/pygooglenews/__init__.py +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/sportsball.egg-info/SOURCES.txt +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/sportsball.egg-info/dependency_links.txt +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/sportsball.egg-info/entry_points.txt +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/sportsball.egg-info/not-zip-safe +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/sportsball.egg-info/top_level.txt +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/tests/__init__.py +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/tests/data/__init__.py +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/tests/data/afl/__init__.py +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/tests/data/afl/afl/__init__.py +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/tests/data/afl/afl/afl_afl_game_model_test.py +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/tests/data/afl/afl/afl_afl_league_model_test.py +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/tests/data/afl/afltables/__init__.py +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/tests/data/afl/afltables/afl_afltables_coach_model_test.py +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/tests/data/afl/afltables/afl_afltables_game_model_test.py +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/tests/data/afl/afltables/afl_afltables_league_model_test.py +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/tests/data/afl/afltables/afl_afltables_player_model_test.py +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/tests/data/aussportsbetting/__init__.py +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/tests/data/aussportsbetting/aussportsbetting_game_model_test.py +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/tests/data/combined/__init__.py +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/tests/data/combined/combined_game_model_test.py +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/tests/data/combined/combined_player_model_test.py +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/tests/data/combined/combined_team_model_test.py +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/tests/data/combined/combined_venue_model_test.py +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/tests/data/espn/__init__.py +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/tests/data/espn/espn_game_model_test.py +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/tests/data/espn/espn_player_model_test.py +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/tests/data/game_model_test.py +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/tests/data/google/__init__.py +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/tests/data/google/google_address_model_test.py +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/tests/data/google/google_news_model_test.py +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/tests/data/hkjc/__init__.py +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/tests/data/hkjc/hkjc/__init__.py +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/tests/data/hkjc/hkjc/hkjc_hkjc_game_model_test.py +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/tests/data/hkjc/hkjc/hkjc_hkjc_player_model_test.py +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/tests/data/nba/__init__.py +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/tests/data/nba/nba/__init__.py +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/tests/data/nba/nba/nba_nba_game_model_test.py +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/tests/data/nba/nba/nba_nba_league_model_test.py +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/tests/data/nba/nba/nba_nba_team_model_test.py +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/tests/data/nba/sportsdb/__init__.py +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/tests/data/nba/sportsdb/nba_sportsdb_league_model_test.py +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/tests/data/nba/sportsreference/__init__.py +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/tests/data/nba/sportsreference/nba_sportsreference_league_model_test.py +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/tests/data/ncaab/__init__.py +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/tests/data/ncaab/sportsreference/__init__.py +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/tests/data/ncaab/sportsreference/ncaab_sportsreference_league_model_test.py +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/tests/data/nfl/__init__.py +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/tests/data/nfl/sportsdb/__init__.py +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/tests/data/nfl/sportsdb/nfl_sportsdb_league_model_test.py +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/tests/data/oddsportal/__init__.py +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/tests/data/oddsportal/decrypt_test.py +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/tests/data/oddsportal/oddsportal_game_model_test.py +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/tests/data/oddsportal/oddsportal_league_model_test.py +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/tests/data/player_model_test.py +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/tests/data/social_model_test.py +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/tests/data/sportsdb/__init__.py +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/tests/data/sportsdb/sportsdb_game_model_test.py +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/tests/data/sportsdb/sportsdb_league_model_test.py +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/tests/data/sportsdb/sportsdb_team_model_test.py +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/tests/data/sportsdb/sportsdb_venue_model_test.py +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/tests/data/sportsreference/__init__.py +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/tests/data/sportsreference/sportsreference_coach_model_test.py +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/tests/data/sportsreference/sportsreference_game_model_test.py +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/tests/data/sportsreference/sportsreference_league_model_test.py +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/tests/data/sportsreference/sportsreference_player_model_test.py +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/tests/data/sportsreference/sportsreference_team_model_test.py +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/tests/data/sportsreference/sportsreference_venue_model_test.py +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/tests/data/team_model_test.py +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/tests/data/x/__init__.py +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/tests/data/x/x_social_model_test.py +0 -0
- {sportsball-0.10.12 → sportsball-0.10.13}/tests/sportsball_test.py +0 -0
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.2
|
2
2
|
Name: sportsball
|
3
|
-
Version: 0.10.
|
3
|
+
Version: 0.10.13
|
4
4
|
Summary: A library for pulling in and normalising sports stats.
|
5
5
|
Home-page: https://github.com/8W9aG/sportsball
|
6
6
|
Author: Will Sackfield
|
@@ -47,7 +47,7 @@ Requires-Dist: playwright>=1.51.0
|
|
47
47
|
Requires-Dist: cchardet>=2.2.0a2
|
48
48
|
Requires-Dist: lxml>=5.3.0
|
49
49
|
Requires-Dist: gender-guesser>=0.4.0
|
50
|
-
Requires-Dist: scrapesession>=0.0.
|
50
|
+
Requires-Dist: scrapesession>=0.0.11
|
51
51
|
Requires-Dist: pyhigh>=0.0.6
|
52
52
|
Dynamic: author
|
53
53
|
Dynamic: author-email
|
@@ -26,7 +26,7 @@ def install_requires() -> typing.List[str]:
|
|
26
26
|
|
27
27
|
setup(
|
28
28
|
name='sportsball',
|
29
|
-
version='0.10.
|
29
|
+
version='0.10.13',
|
30
30
|
description='A library for pulling in and normalising sports stats.',
|
31
31
|
long_description=long_description,
|
32
32
|
long_description_content_type='text/markdown',
|
@@ -15,7 +15,7 @@ from scrapesession.scrapesession import ScrapeSession # type: ignore
|
|
15
15
|
from ....playwright import ensure_install
|
16
16
|
from ...game_model import VERSION, GameModel
|
17
17
|
from ...league import League
|
18
|
-
from ...league_model import LeagueModel
|
18
|
+
from ...league_model import SHUTDOWN_FLAG, LeagueModel
|
19
19
|
from ..position import Position, position_from_str
|
20
20
|
from .afl_afl_game_model import create_afl_afl_game_model, parse_players_v1
|
21
21
|
|
@@ -28,6 +28,8 @@ def _parse_v1(
|
|
28
28
|
playwright: Playwright,
|
29
29
|
) -> Iterator[GameModel]:
|
30
30
|
for div in soup.find_all("div", {"class": re.compile(".*js-match-list-item.*")}):
|
31
|
+
if SHUTDOWN_FLAG.is_set():
|
32
|
+
return
|
31
33
|
team_names = []
|
32
34
|
for span in div.find_all(
|
33
35
|
"span", {"class": re.compile(".*team-lineups__team-name.*")}
|
@@ -77,6 +79,8 @@ def _parse_v2_soup(
|
|
77
79
|
tuple[list[str], list[list[tuple[str, str, str, str, Position]]], str, str]
|
78
80
|
]:
|
79
81
|
for div in soup.find_all("div", {"class": "team-lineups__item"}):
|
82
|
+
if SHUTDOWN_FLAG.is_set():
|
83
|
+
return
|
80
84
|
team_names = []
|
81
85
|
for span in div.find_all(
|
82
86
|
"span", {"class": re.compile(".*team-lineups-header__name.*")}
|
@@ -218,12 +222,18 @@ class AFLAFLLeagueModel(LeagueModel):
|
|
218
222
|
|
219
223
|
@property
|
220
224
|
def games(self) -> Iterator[GameModel]:
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
225
|
+
try:
|
226
|
+
ladder = self._ladder
|
227
|
+
ensure_install()
|
228
|
+
with sync_playwright() as p:
|
229
|
+
browser = p.chromium.launch()
|
230
|
+
context = browser.new_context()
|
231
|
+
page = context.new_page()
|
232
|
+
url = "https://www.afl.com.au/matches/team-lineups"
|
233
|
+
page.goto(url, wait_until="networkidle")
|
234
|
+
yield from _parse_game_info(
|
235
|
+
page.content(), self.session, ladder, url, p
|
236
|
+
)
|
237
|
+
except Exception as exc:
|
238
|
+
SHUTDOWN_FLAG.set()
|
239
|
+
raise exc
|
@@ -15,7 +15,7 @@ from scrapesession.scrapesession import ScrapeSession # type: ignore
|
|
15
15
|
|
16
16
|
from ...game_model import GameModel
|
17
17
|
from ...league import League
|
18
|
-
from ...league_model import LeagueModel
|
18
|
+
from ...league_model import SHUTDOWN_FLAG, LeagueModel
|
19
19
|
from ...season_type import SeasonType
|
20
20
|
from .afl_afltables_game_model import create_afl_afltables_game_model
|
21
21
|
|
@@ -82,6 +82,8 @@ class AFLAFLTablesLeagueModel(LeagueModel):
|
|
82
82
|
if "Venue:" in td_text:
|
83
83
|
current_dt = _find_dt(td_text, season_url)
|
84
84
|
for a in table.find_all("a", href=True):
|
85
|
+
if SHUTDOWN_FLAG.is_set():
|
86
|
+
return
|
85
87
|
if a.get_text().strip().lower() == "match stats":
|
86
88
|
url = urllib.parse.urljoin(season_url, a.get("href"))
|
87
89
|
if url in urls_duplicates:
|
@@ -149,20 +151,24 @@ class AFLAFLTablesLeagueModel(LeagueModel):
|
|
149
151
|
|
150
152
|
@property
|
151
153
|
def games(self) -> Iterator[GameModel]:
|
152
|
-
|
153
|
-
with self.session.
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
for
|
160
|
-
for
|
161
|
-
for
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
154
|
+
try:
|
155
|
+
with self.session.cache_disabled():
|
156
|
+
with self.session.wayback_disabled():
|
157
|
+
response = self.session.get(_SEASON_URL)
|
158
|
+
response.raise_for_status()
|
159
|
+
soup = BeautifulSoup(response.text, "lxml")
|
160
|
+
with tqdm.tqdm(position=self.position) as pbar:
|
161
|
+
for table in soup.find_all("table"):
|
162
|
+
for tr in table.find_all("tr"):
|
163
|
+
for td in tr.find_all("td"):
|
164
|
+
for a in td.find_all("a"):
|
165
|
+
url = urllib.parse.urljoin(_SEASON_URL, a.get("href"))
|
166
|
+
yield from self._produce_games(
|
167
|
+
url, SeasonType.REGULAR, pbar
|
168
|
+
)
|
169
|
+
yield from self._produce_games(
|
170
|
+
url, SeasonType.POSTSEASON, pbar
|
171
|
+
)
|
172
|
+
except Exception as exc:
|
173
|
+
SHUTDOWN_FLAG.set()
|
174
|
+
raise exc
|
@@ -11,7 +11,7 @@ from scrapesession.scrapesession import ScrapeSession # type: ignore
|
|
11
11
|
|
12
12
|
from ..game_model import GameModel
|
13
13
|
from ..league import League
|
14
|
-
from ..league_model import LeagueModel
|
14
|
+
from ..league_model import SHUTDOWN_FLAG, LeagueModel
|
15
15
|
from .aussportsbetting_game_model import create_aussportsbetting_game_model
|
16
16
|
|
17
17
|
|
@@ -98,17 +98,23 @@ class AusSportsBettingLeagueModel(LeagueModel):
|
|
98
98
|
|
99
99
|
@property
|
100
100
|
def games(self) -> Iterator[GameModel]:
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
101
|
+
try:
|
102
|
+
with self.session.cache_disabled():
|
103
|
+
response = self.session.get(self._spreadsheet_url)
|
104
|
+
response.raise_for_status()
|
105
|
+
workbook = load_workbook(filename=BytesIO(response.content))
|
106
|
+
ws = workbook.active
|
107
|
+
if ws is None:
|
108
|
+
raise ValueError("ws is null.")
|
109
|
+
with tqdm.tqdm(position=self.position) as pbar:
|
110
|
+
for row in ws.iter_rows():
|
111
|
+
if SHUTDOWN_FLAG.is_set():
|
112
|
+
return
|
113
|
+
game_model = self._row_to_game(row)
|
114
|
+
if game_model is not None:
|
115
|
+
pbar.update(1)
|
116
|
+
pbar.set_description(f"AusSportsBetting - {game_model.dt}")
|
117
|
+
yield game_model
|
118
|
+
except Exception as exc:
|
119
|
+
SHUTDOWN_FLAG.set()
|
120
|
+
raise exc
|
@@ -8,7 +8,7 @@ from scrapesession.scrapesession import ScrapeSession # type: ignore
|
|
8
8
|
|
9
9
|
from ..game_model import GameModel
|
10
10
|
from ..league import League
|
11
|
-
from ..league_model import LeagueModel
|
11
|
+
from ..league_model import SHUTDOWN_FLAG, LeagueModel
|
12
12
|
from ..season_type import SeasonType
|
13
13
|
from .espn_game_model import create_espn_game_model
|
14
14
|
|
@@ -136,6 +136,8 @@ class ESPNLeagueModel(LeagueModel):
|
|
136
136
|
weeks_response.raise_for_status()
|
137
137
|
weeks = weeks_response.json()
|
138
138
|
for item in weeks["items"]:
|
139
|
+
if SHUTDOWN_FLAG.is_set():
|
140
|
+
return
|
139
141
|
if cache_disabled:
|
140
142
|
with self.session.cache_disabled():
|
141
143
|
week_response = self.session.get(item["$ref"])
|
@@ -153,35 +155,43 @@ class ESPNLeagueModel(LeagueModel):
|
|
153
155
|
|
154
156
|
@property
|
155
157
|
def games(self) -> Iterator[GameModel]:
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
158
|
+
try:
|
159
|
+
with self.session.wayback_disabled():
|
160
|
+
page = 1
|
161
|
+
first = True
|
162
|
+
with tqdm.tqdm(position=self.position) as pbar:
|
163
|
+
while True:
|
164
|
+
if page == 1:
|
165
|
+
with self.session.cache_disabled():
|
166
|
+
response = self.session.get(
|
167
|
+
self._start_url + f"&page={page}"
|
168
|
+
)
|
169
|
+
else:
|
163
170
|
response = self.session.get(
|
164
171
|
self._start_url + f"&page={page}"
|
165
172
|
)
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
173
|
+
response.raise_for_status()
|
174
|
+
seasons = response.json()
|
175
|
+
for item in seasons.get("items", []):
|
176
|
+
season_response = self.session.get(item["$ref"])
|
177
|
+
season_response.raise_for_status()
|
178
|
+
season_json = season_response.json()
|
179
|
+
|
180
|
+
for season_item in season_json["types"]["items"]:
|
181
|
+
season_type_response = self.session.get(
|
182
|
+
season_item["$ref"]
|
183
|
+
)
|
184
|
+
season_type_response.raise_for_status()
|
185
|
+
season_type_json = season_type_response.json()
|
186
|
+
|
187
|
+
yield from self._produce_week_games(
|
188
|
+
season_type_json, page, pbar, first
|
189
|
+
)
|
190
|
+
first = False
|
191
|
+
|
192
|
+
if page >= seasons.get("pageCount", 0):
|
193
|
+
break
|
194
|
+
page += 1
|
195
|
+
except Exception as exc:
|
196
|
+
SHUTDOWN_FLAG.set()
|
197
|
+
raise exc
|
@@ -18544,6 +18544,16 @@ _CACHED_GEOCODES: dict[str, Any] = {
|
|
18544
18544
|
housenumber="",
|
18545
18545
|
country="USA",
|
18546
18546
|
),
|
18547
|
+
"Canadian Tire Centre, Ottawa, ON, Canada": SportsballGeocodeTuple(
|
18548
|
+
city="Ottawa",
|
18549
|
+
state="ON",
|
18550
|
+
postal="",
|
18551
|
+
lat=45.296944,
|
18552
|
+
lng=-75.927222,
|
18553
|
+
housenumber="",
|
18554
|
+
country="Canada",
|
18555
|
+
),
|
18556
|
+
"American Airlines Center": AMERICAN_AIRLINES_ARENA,
|
18547
18557
|
}
|
18548
18558
|
|
18549
18559
|
|
@@ -0,0 +1,111 @@
|
|
1
|
+
"""The HKJC league model."""
|
2
|
+
|
3
|
+
# pylint: disable=line-too-long,too-many-statements
|
4
|
+
import datetime
|
5
|
+
import http
|
6
|
+
import urllib.parse
|
7
|
+
from typing import Iterator
|
8
|
+
from urllib.parse import urlparse
|
9
|
+
|
10
|
+
import tqdm
|
11
|
+
from bs4 import BeautifulSoup
|
12
|
+
from scrapesession.scrapesession import ScrapeSession # type: ignore
|
13
|
+
|
14
|
+
from ...game_model import GameModel
|
15
|
+
from ...league import League
|
16
|
+
from ...league_model import SHUTDOWN_FLAG, LeagueModel
|
17
|
+
from .hkjc_hkjc_game_model import (RACE_COURSE_QUERY_KEY, RACE_DATE_QUERY_KEY,
|
18
|
+
RACE_NUMBER_QUERY_KEY,
|
19
|
+
create_hkjc_hkjc_game_model)
|
20
|
+
from .hkjc_hkjc_venue_model import HAPPY_VALLEY_VENUE_CODE, SHA_TIN_VENUE_CODE
|
21
|
+
|
22
|
+
_BAD_URLS = {
|
23
|
+
"https://common.hkjc.com/racing/information/English/Racing/LocalResults.aspx?RaceDate=2025/03/05&Racecourse=HV&RaceNo=9",
|
24
|
+
"https://common.hkjc.com/racing/information/English/Racing/LocalResults.aspx?RaceDate=1992/04/22&Racecourse=HV&RaceNo=4",
|
25
|
+
"https://common.hkjc.com/racing/information/English/Racing/LocalResults.aspx?RaceDate=1992/04/22&Racecourse=HV&RaceNo=5",
|
26
|
+
"https://common.hkjc.com/racing/information/English/Racing/LocalResults.aspx?RaceDate=1992/04/22&Racecourse=HV&RaceNo=6",
|
27
|
+
}
|
28
|
+
|
29
|
+
|
30
|
+
class HKJCHKJCLeagueModel(LeagueModel):
|
31
|
+
"""HKJC HKJC implementation of the league model."""
|
32
|
+
|
33
|
+
def __init__(self, session: ScrapeSession, position: int | None = None) -> None:
|
34
|
+
super().__init__(League.HKJC, session, position=position)
|
35
|
+
|
36
|
+
@classmethod
|
37
|
+
def name(cls) -> str:
|
38
|
+
return "hkjc-league-model"
|
39
|
+
|
40
|
+
@property
|
41
|
+
def games(self) -> Iterator[GameModel]: # type: ignore
|
42
|
+
try:
|
43
|
+
|
44
|
+
def games_for_date(dt: datetime.date) -> Iterator[GameModel]:
|
45
|
+
dt_str = dt.strftime("%Y/%m/%d")
|
46
|
+
for course in [SHA_TIN_VENUE_CODE, HAPPY_VALLEY_VENUE_CODE]:
|
47
|
+
with self.session.wayback_disabled():
|
48
|
+
response = self.session.get(
|
49
|
+
f"https://racing.hkjc.com/racing/information/English/Racing/LocalResults.aspx?{RACE_DATE_QUERY_KEY}={dt_str}&{RACE_COURSE_QUERY_KEY}={course}&{RACE_NUMBER_QUERY_KEY}=1",
|
50
|
+
)
|
51
|
+
response.raise_for_status()
|
52
|
+
game_model = create_hkjc_hkjc_game_model(
|
53
|
+
self.session, response.text, response.url
|
54
|
+
)
|
55
|
+
if game_model is not None:
|
56
|
+
yield game_model
|
57
|
+
soup = BeautifulSoup(response.text, "lxml")
|
58
|
+
seen_urls = {response.url}
|
59
|
+
for a in soup.find_all("a", href=True):
|
60
|
+
if SHUTDOWN_FLAG.is_set():
|
61
|
+
return
|
62
|
+
url = urllib.parse.urljoin(response.url, a.get("href"))
|
63
|
+
if url in seen_urls:
|
64
|
+
continue
|
65
|
+
o = urlparse(url)
|
66
|
+
if not o.path.endswith("/LocalResults.aspx"):
|
67
|
+
continue
|
68
|
+
if url in _BAD_URLS:
|
69
|
+
continue
|
70
|
+
query = urllib.parse.parse_qs(o.query)
|
71
|
+
if RACE_NUMBER_QUERY_KEY not in query:
|
72
|
+
continue
|
73
|
+
if query[RACE_COURSE_QUERY_KEY][0] != course:
|
74
|
+
continue
|
75
|
+
with self.session.wayback_disabled():
|
76
|
+
response = self.session.get(url)
|
77
|
+
if response.status_code == http.HTTPStatus.NOT_FOUND:
|
78
|
+
continue
|
79
|
+
response.raise_for_status()
|
80
|
+
game_model = create_hkjc_hkjc_game_model(
|
81
|
+
self.session, response.text, response.url
|
82
|
+
)
|
83
|
+
if game_model is not None:
|
84
|
+
yield game_model
|
85
|
+
seen_urls.add(url)
|
86
|
+
|
87
|
+
today_date = datetime.datetime.today().date()
|
88
|
+
last_scraped_date: datetime.date | None = None
|
89
|
+
current_date = today_date
|
90
|
+
|
91
|
+
with tqdm.tqdm(position=self.position) as pbar:
|
92
|
+
while (
|
93
|
+
last_scraped_date is None
|
94
|
+
or (last_scraped_date - current_date).days < 360
|
95
|
+
):
|
96
|
+
if current_date >= today_date:
|
97
|
+
with self.session.cache_disabled():
|
98
|
+
for game_model in games_for_date(current_date):
|
99
|
+
last_scraped_date = current_date
|
100
|
+
pbar.update(1)
|
101
|
+
yield game_model
|
102
|
+
else:
|
103
|
+
for game_model in games_for_date(current_date):
|
104
|
+
last_scraped_date = current_date
|
105
|
+
pbar.update(1)
|
106
|
+
yield game_model
|
107
|
+
pbar.set_description(f"HKJC {current_date}")
|
108
|
+
current_date -= datetime.timedelta(days=1)
|
109
|
+
except Exception as exc:
|
110
|
+
SHUTDOWN_FLAG.set()
|
111
|
+
raise exc
|
@@ -2,6 +2,7 @@
|
|
2
2
|
|
3
3
|
# pylint: disable=line-too-long
|
4
4
|
import datetime
|
5
|
+
import threading
|
5
6
|
from typing import Iterator, get_args, get_origin
|
6
7
|
|
7
8
|
import pandas as pd
|
@@ -19,6 +20,7 @@ from .model import Model
|
|
19
20
|
from .venue_model import VENUE_ADDRESS_COLUMN
|
20
21
|
|
21
22
|
LEAGUE_COLUMN = "league"
|
23
|
+
SHUTDOWN_FLAG = threading.Event()
|
22
24
|
|
23
25
|
|
24
26
|
def _clear_column_list(df: pd.DataFrame) -> pd.DataFrame:
|
@@ -13,7 +13,7 @@ from scrapesession.scrapesession import ScrapeSession # type: ignore
|
|
13
13
|
|
14
14
|
from ...game_model import GameModel
|
15
15
|
from ...league import League
|
16
|
-
from ...league_model import LeagueModel
|
16
|
+
from ...league_model import SHUTDOWN_FLAG, LeagueModel
|
17
17
|
from .nba_nba_game_model import create_nba_nba_game_model
|
18
18
|
|
19
19
|
|
@@ -83,6 +83,8 @@ class NBANBALeagueModel(LeagueModel):
|
|
83
83
|
pbar: tqdm.tqdm,
|
84
84
|
) -> Iterator[GameModel]:
|
85
85
|
for _, row in all_games.iterrows():
|
86
|
+
if SHUTDOWN_FLAG.is_set():
|
87
|
+
return
|
86
88
|
season_id = row["SEASON_ID"]
|
87
89
|
dt = parse(row["GAME_DATE"])
|
88
90
|
season_info = seasons.get(
|
@@ -112,30 +114,34 @@ class NBANBALeagueModel(LeagueModel):
|
|
112
114
|
|
113
115
|
@property
|
114
116
|
def games(self) -> Iterator[GameModel]:
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
117
|
+
try:
|
118
|
+
to_date = datetime.datetime.today().date()
|
119
|
+
seasons: dict[str, NBANBALeagueModel._SeasonInfo] = {}
|
120
|
+
first_call = False
|
121
|
+
with tqdm.tqdm(position=self.position) as pbar:
|
122
|
+
while True:
|
123
|
+
next_date = to_date - relativedelta(years=1)
|
124
|
+
if not first_call:
|
125
|
+
with self.session.cache_disabled():
|
126
|
+
result = leaguegamefinder.LeagueGameFinder(
|
127
|
+
league_id_nullable=self._league_id,
|
128
|
+
date_from_nullable=next_date.strftime("%m/%d/%Y"),
|
129
|
+
date_to_nullable=to_date.strftime("%m/%d/%Y"),
|
130
|
+
)
|
131
|
+
first_call = True
|
132
|
+
else:
|
123
133
|
result = leaguegamefinder.LeagueGameFinder(
|
124
134
|
league_id_nullable=self._league_id,
|
125
135
|
date_from_nullable=next_date.strftime("%m/%d/%Y"),
|
126
136
|
date_to_nullable=to_date.strftime("%m/%d/%Y"),
|
127
137
|
)
|
128
|
-
first_call = True
|
129
|
-
else:
|
130
|
-
result = leaguegamefinder.LeagueGameFinder(
|
131
|
-
league_id_nullable=self._league_id,
|
132
|
-
date_from_nullable=next_date.strftime("%m/%d/%Y"),
|
133
|
-
date_to_nullable=to_date.strftime("%m/%d/%Y"),
|
134
|
-
)
|
135
138
|
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
139
|
+
all_games = _combine_team_games(result.get_data_frames()[0])
|
140
|
+
all_games = all_games.sort_values(by="GAME_DATE", ascending=True)
|
141
|
+
if all_games.empty:
|
142
|
+
break
|
143
|
+
yield from self._produce_games(all_games, seasons, pbar)
|
144
|
+
to_date = next_date
|
145
|
+
except Exception as exc:
|
146
|
+
SHUTDOWN_FLAG.set()
|
147
|
+
raise exc
|
@@ -0,0 +1,46 @@
|
|
1
|
+
"""NBA NBA.com league model."""
|
2
|
+
|
3
|
+
# pylint: disable=too-many-statements,protected-access,too-many-locals,bare-except,too-many-branches,duplicate-code
|
4
|
+
import datetime
|
5
|
+
import logging
|
6
|
+
from typing import Iterator
|
7
|
+
|
8
|
+
from scrapesession.scrapesession import ScrapeSession # type: ignore
|
9
|
+
|
10
|
+
from ...game_model import VERSION, GameModel
|
11
|
+
from ...league import League
|
12
|
+
from ...league_model import SHUTDOWN_FLAG, LeagueModel
|
13
|
+
from .nba_nbacom_game_model import create_nba_nbacom_game_model
|
14
|
+
|
15
|
+
|
16
|
+
class NBANBAComLeagueModel(LeagueModel):
|
17
|
+
"""NBA NBA.com implementation of the league model."""
|
18
|
+
|
19
|
+
def __init__(self, session: ScrapeSession, position: int | None = None) -> None:
|
20
|
+
super().__init__(League.AFL, session, position=position)
|
21
|
+
|
22
|
+
@classmethod
|
23
|
+
def name(cls) -> str:
|
24
|
+
return "nba-nbacom-league-model"
|
25
|
+
|
26
|
+
@property
|
27
|
+
def games(self) -> Iterator[GameModel]:
|
28
|
+
try:
|
29
|
+
with self.session.cache_disabled():
|
30
|
+
date_slug = datetime.datetime.today().date().strftime("%Y%m%d")
|
31
|
+
response = self.session.get(
|
32
|
+
f"https://stats.nba.com/js/data/leaders/00_daily_lineups_{date_slug}.json"
|
33
|
+
)
|
34
|
+
if response.ok:
|
35
|
+
lineup = response.json()
|
36
|
+
for game in lineup["games"]:
|
37
|
+
if SHUTDOWN_FLAG.is_set():
|
38
|
+
return
|
39
|
+
yield create_nba_nbacom_game_model(
|
40
|
+
game=game, session=self.session, version=VERSION
|
41
|
+
)
|
42
|
+
else:
|
43
|
+
logging.warning("Failed to fetch NBA daily lineups.")
|
44
|
+
except Exception as exc:
|
45
|
+
SHUTDOWN_FLAG.set()
|
46
|
+
raise exc
|
{sportsball-0.10.12 → sportsball-0.10.13}/sportsball/data/oddsportal/oddsportal_league_model.py
RENAMED
@@ -15,7 +15,7 @@ from scrapesession.scrapesession import ScrapeSession # type: ignore
|
|
15
15
|
|
16
16
|
from ..game_model import GameModel
|
17
17
|
from ..league import League
|
18
|
-
from ..league_model import LeagueModel
|
18
|
+
from ..league_model import SHUTDOWN_FLAG, LeagueModel
|
19
19
|
from .decrypt import fetch_data
|
20
20
|
from .oddsportal_game_model import create_oddsportal_game_model
|
21
21
|
|
@@ -63,6 +63,8 @@ def _process_results_pages(
|
|
63
63
|
if d.get("total") == 0:
|
64
64
|
return
|
65
65
|
for row in d.get("rows", []):
|
66
|
+
if SHUTDOWN_FLAG.is_set():
|
67
|
+
return
|
66
68
|
game_model = create_oddsportal_game_model(
|
67
69
|
session, urllib.parse.urljoin(url, row["url"]), league, False
|
68
70
|
)
|
@@ -165,6 +167,10 @@ class OddsPortalLeagueModel(LeagueModel):
|
|
165
167
|
|
166
168
|
@property
|
167
169
|
def games(self) -> Iterator[GameModel]:
|
168
|
-
|
169
|
-
|
170
|
-
|
170
|
+
try:
|
171
|
+
with tqdm.tqdm(position=self.position) as pbar:
|
172
|
+
yield from self._find_next(pbar)
|
173
|
+
yield from self._find_previous(pbar)
|
174
|
+
except Exception as exc:
|
175
|
+
SHUTDOWN_FLAG.set()
|
176
|
+
raise exc
|