def test_contract(self): james = lebron_james() assert james.contract assert len(james.contract.years) == 3 assert all([year.season for year in james.contract.years]) assert all([year.amount for year in james.contract.years]) first_year = james.contract.years[0] assert first_year.season == "2019-20" assert first_year.amount == 37436858 assert first_year.option is None third_year = james.contract.years[2] assert third_year.season == "2021-22" assert third_year.amount == 41002273 # assert third_year.option == "Player" chamberlain = wilt_chamberlain() assert not chamberlain.contract shayok = PlayerPageScraper(get_resource("shayok.html")).get_content() assert not shayok.contract simons = PlayerPageScraper( get_resource("anfernee_simons.html")).get_content() assert simons.contract.years[0].option == "player" assert simons.contract.years[1].option == "early termination" assert simons.contract.years[2].option == "team"
def test_stats_where_partially_available(self): mullin = PlayerPageScraper( get_resource("chris_mullin.html")).get_content() seasons = list(mullin.seasons) rookie_season = seasons[0] assert rookie_season.stats.shooting_data is None final_season = seasons[-1] assert final_season.stats.shooting_data assert final_season.stats.shooting_data.avg_distance == 18.8
def test_game_log(self): # can't store this page locally because we depend on a hyperlink inside seasons = list( PlayerPageScraper( "https://www.basketball-reference.com/players/m/mbengdj01.html" ).get_content().seasons) gl = seasons[0].game_logs() assert len([game for game in gl if game.played]) == seasons[0].stats.games_played
def test_career_stats_encapsulated(self): mullin = PlayerPageScraper( get_resource("chris_mullin.html")).get_content() career_stats = mullin.career_stats first_season = next(mullin.seasons) first_playoffs = next(mullin.playoffs) for attr in ["age", "all_star", "team", "season"]: assert not hasattr(career_stats, attr) assert hasattr(first_season, attr) assert hasattr(first_playoffs, attr)
def test_playoff_games(self): lbj = PlayerPageScraper( "https://www.basketball-reference.com/players/j/jamesle01.html" ).get_content() po = next(lbj.playoffs) assert po.stats.points == 400 games = list(po.game_logs()) assert len(games) == 13 game: GameLog = games[0] assert game.date == date(2006, 4, 22) assert game.points == 32 assert game.assists == 11
def test_shooting_data(self): lbj = PlayerPageScraper( "https://www.basketball-reference.com/players/j/jamesle01.html" ).get_content() first_season = next(lbj.seasons) shooting_data = first_season.stats.shooting_data assert shooting_data.heaves_made == 0 assert shooting_data.heaves_attempted == 3 assert shooting_data.corner_three_point_fgp == 0.323 assert shooting_data.corner_three_point_fga == 0.286 assert shooting_data.three_point_fga_assisted == 0.746 assert shooting_data.dunks_made == 91 assert shooting_data.dunks_fga == 0.064 assert shooting_data.two_point_fga_assisted == 0.442 assert shooting_data.fgp_by_distance assert shooting_data.fga_by_distance assert shooting_data.fga_by_distance.two_point == 0.855 assert shooting_data.fga_by_distance.zero_three == 0.315 assert shooting_data.fga_by_distance.three_ten == 0.168 assert shooting_data.fga_by_distance.ten_sixteen == 0.161 assert shooting_data.fga_by_distance.sixteen_three_pt == 0.211 assert shooting_data.fga_by_distance.three_point == 0.145 assert shooting_data.fgp_by_distance.two_point == 0.438 assert shooting_data.fgp_by_distance.zero_three == 0.604 assert shooting_data.fgp_by_distance.three_ten == 0.356 assert shooting_data.fgp_by_distance.ten_sixteen == 0.313 assert shooting_data.fgp_by_distance.sixteen_three_pt == 0.352 assert shooting_data.fgp_by_distance.three_point == 0.290 career_sd = lbj.career_stats.shooting_data assert career_sd.dunks_made == 1898 assert career_sd.dunks_fga == 0.08 assert career_sd.heaves_made == 2 assert career_sd.heaves_attempted == 34 assert career_sd.two_point_fga_assisted == 0.347 assert career_sd.three_point_fga_assisted == 0.469 assert career_sd.corner_three_point_fga == 0.129 assert career_sd.corner_three_point_fgp == 0.387 assert career_sd.avg_distance == 12.0 first_playoffs = next(lbj.playoffs) assert first_playoffs.stats.shooting_data.avg_distance == 12.1 assert first_playoffs.stats.shooting_data.dunks_made == 13
def test_stats_where_none_available(self): chamberlain = PlayerPageScraper( get_resource("chamberlain.html")).get_content() rookie_season = next(chamberlain.seasons) assert rookie_season.stats.rebounds is None assert rookie_season.stats.offensive_rebounds is None assert rookie_season.stats.defensive_rebounds is None assert rookie_season.stats.turnovers is None assert rookie_season.stats.three_fg_percentage is None assert rookie_season.stats.three_fg_made is None assert rookie_season.stats.three_fg_attempted is None assert rookie_season.stats.shooting_data is None advanced_stats = rookie_season.stats.advanced assert advanced_stats.value_over_replacement_player is None assert advanced_stats.ft_attempt_rate == 0.429 assert advanced_stats.assist_percentage is None assert advanced_stats.offensive_rebound_percentage is None assert advanced_stats.defensive_rebound_percentage is None assert advanced_stats.usage_percentage is None
def scrape_all(self, _max: int = None) -> Iterator[Player]: urls = list(set(self._urls[0:_max] if _max else self._urls)) with concurrent.futures.ThreadPoolExecutor() as executor: for player in executor.map(lambda u: PlayerPageScraper(u).get_content(), urls): yield player
def get_by_name(name: str) -> Optional[Player]: result = Search.search_players(name) if not result: return None url = result[0][-1] return PlayerPageScraper(url).get_content()
def get_by_id(_id: str) -> Player: url = f"https://www.basketball-reference.com/players/{_id[0]}/{_id}.html" return PlayerPageScraper(url).get_content()
def get_by_url(url: str) -> Player: return PlayerPageScraper(url).get_content()
def as_player(self) -> Player: from bballer.scrapers.PlayerPageScraper import PlayerPageScraper scr = PlayerPageScraper(self.url) return scr.get_content()
def test_all_star(self): erving = PlayerPageScraper( get_resource("julius_erving.html")).get_content() assert len([ season for season in list(erving.seasons) if season.all_star ]) == 11
def wilt_chamberlain(): return PlayerPageScraper(get_resource("chamberlain.html")).get_content()
def test_seasons(self): erving = PlayerPageScraper( get_resource("julius_erving.html")).get_content() assert len(list(erving.seasons)) == 11 # ABA seasons must be discarded
class TestStats: player = PlayerPageScraper( get_resource("carmelo_anthony.html")).get_content() seasons = list(player.seasons) rookie_season = seasons[0] def test_season_stats(self): rookie_season = self.rookie_season assert repr(rookie_season).endswith("(2004, DEN)") assert rookie_season.stats.position == "SF" assert rookie_season.season == 2004 assert rookie_season.stats.games_started == 82 assert rookie_season.stats.games_played == 82 assert rookie_season.stats.minutes_played == 2995 assert rookie_season.stats.fg_attempted == 1465 assert rookie_season.stats.fg_made == 624 assert rookie_season.stats.three_fg_made == 69 assert rookie_season.stats.three_fg_attempted == 214 assert rookie_season.stats.two_fg_attempted == 1251 assert rookie_season.stats.two_fg_made == 555 assert rookie_season.stats.effective_fg_percentage == 0.449 assert rookie_season.stats.ft_made == 408 assert rookie_season.stats.ft_attempted == 525 assert rookie_season.stats.offensive_rebounds == 183 assert rookie_season.stats.defensive_rebounds == 315 assert rookie_season.stats.rebounds == 498 assert round(rookie_season.stats.two_fg_percentage, 3) == 0.444 assert rookie_season.stats.fg_percentage == 0.426 assert rookie_season.stats.three_fg_percentage == 0.322 assert rookie_season.stats.free_throw_percentage == 0.777 assert not rookie_season.all_star assert rookie_season.stats.assists == 227 assert rookie_season.stats.blocks == 41 assert rookie_season.stats.turnovers == 247 assert rookie_season.stats.steals == 97 assert rookie_season.stats.fouls == 225 assert rookie_season.stats.points == 1725 def test_advanced_stats(self): rookie_season = self.rookie_season assert repr(rookie_season.stats.advanced) == "AdvancedStatLine(2004)" assert rookie_season.stats.advanced.assist_percentage == 13.8 assert rookie_season.stats.advanced.player_efficiency_rating == 17.6 assert rookie_season.stats.advanced.true_shooting_percentage == 0.509 assert rookie_season.stats.advanced.three_fg_attempt_rate == 0.146 assert rookie_season.stats.advanced.ft_attempt_rate == 0.358 assert rookie_season.stats.advanced.offensive_rebound_percentage == 6.8 assert rookie_season.stats.advanced.defensive_rebound_percentage == 12.1 assert rookie_season.stats.advanced.total_rebound_percentage == 9.4 assert rookie_season.stats.advanced.steal_percentage == 1.7 assert rookie_season.stats.advanced.block_percentage == 1.0 assert rookie_season.stats.advanced.turnover_percentage == 12.7 assert rookie_season.stats.advanced.usage_percentage == 28.5 assert rookie_season.stats.advanced.offensive_win_shares == 3.7 assert rookie_season.stats.advanced.defensive_win_shares == 2.4 assert rookie_season.stats.advanced.win_shares == 6.1 assert rookie_season.stats.advanced.win_shares_per_48 == 0.098 assert rookie_season.stats.advanced.offensive_box_plus_minus == 1.2 assert rookie_season.stats.advanced.defensive_box_plus_minus == -1.2 assert rookie_season.stats.advanced.box_plus_minus == 0 assert rookie_season.stats.advanced.value_over_replacement_player == 1.6 def test_stats_where_none_available(self): chamberlain = PlayerPageScraper( get_resource("chamberlain.html")).get_content() rookie_season = next(chamberlain.seasons) assert rookie_season.stats.rebounds is None assert rookie_season.stats.offensive_rebounds is None assert rookie_season.stats.defensive_rebounds is None assert rookie_season.stats.turnovers is None assert rookie_season.stats.three_fg_percentage is None assert rookie_season.stats.three_fg_made is None assert rookie_season.stats.three_fg_attempted is None assert rookie_season.stats.shooting_data is None advanced_stats = rookie_season.stats.advanced assert advanced_stats.value_over_replacement_player is None assert advanced_stats.ft_attempt_rate == 0.429 assert advanced_stats.assist_percentage is None assert advanced_stats.offensive_rebound_percentage is None assert advanced_stats.defensive_rebound_percentage is None assert advanced_stats.usage_percentage is None def test_stats_where_partially_available(self): mullin = PlayerPageScraper( get_resource("chris_mullin.html")).get_content() seasons = list(mullin.seasons) rookie_season = seasons[0] assert rookie_season.stats.shooting_data is None final_season = seasons[-1] assert final_season.stats.shooting_data assert final_season.stats.shooting_data.avg_distance == 18.8 def test_career_stats_advanced(self): mullin = PlayerPageScraper( get_resource("chris_mullin.html")).get_content() assert mullin.career_stats.advanced.usage_percentage def test_career_stats_encapsulated(self): mullin = PlayerPageScraper( get_resource("chris_mullin.html")).get_content() career_stats = mullin.career_stats first_season = next(mullin.seasons) first_playoffs = next(mullin.playoffs) for attr in ["age", "all_star", "team", "season"]: assert not hasattr(career_stats, attr) assert hasattr(first_season, attr) assert hasattr(first_playoffs, attr)
def julius_erving(): return PlayerPageScraper(get_resource("julius_erving.html")).get_content()
def test_career_stats_advanced(self): mullin = PlayerPageScraper( get_resource("chris_mullin.html")).get_content() assert mullin.career_stats.advanced.usage_percentage
def lebron_james(): return PlayerPageScraper(get_resource("lebron_james.html")).get_content()
def carmelo_anthony(): return PlayerPageScraper( get_resource("carmelo_anthony.html")).get_content()
def test_historical_player(self): player = PlayerPageScraper( get_resource("tom_hawkins.html")).get_content() assert player.name == "Tom Hawkins" assert player.date_of_birth == date(1936, 12, 22)
def test_get_playoff_totals(self): erving = PlayerPageScraper( get_resource("julius_erving.html")).get_content() playoffs = list(erving.playoffs) assert len(playoffs) == 11 assert sum([season.stats.points for season in playoffs]) == 3088