Кбк пфр 2018 1: Полная информация для работы бухгалтера

Scraping Pro Football Reference with Python

Pro Football Reference — это мечта любого статистика — здесь много информации о футболе, она легко доступна прямо на сайте через встроенные API и четко отформатирована, что упрощает сбор данных. занятие, не вызывающее головной боли.

В этом посте рассказывается, как получить исторические очки фэнтези для отдельных игроков с помощью Python. (Вот более старая, более короткая запись с использованием R.) Мы сможем делать подобные графики, которые группируют похожих игроков на основе их среднего балла и дисперсии.

Сложный способ очистить таблицу — вручную получить необработанный HTML-код с запросами , а затем вручную проанализировать структуру таблицы с помощью BeautifulSoup . Но если нам не нужно много точного контроля, есть способ получше.

Самый простой способ очистить таблицу — использовать pandas.read_html . Вот как выглядит скрейп данных Рассела Уилсона за 2018 год с помощью 3 строк кода:

 import pandas
url = 'https://www. pro-football-reference.com/players/W/WilsRu00/fantasy/2018/'
дф = pd.read_html(url)[0]
 
 Безымянный: 0_level_0 Внутри 20 Внутри 10 Snap Count Безымянный: 4_level_0
    Безымянный: 0_level_1 Мимо мчится Мимо мчится...
    Rk G# Date Tm Безымянный: 4_level_2 ...
0 1.0 1.0 09.09.2018 МОРЕ @ ...
1 2.0 2.0 17.09.2018 МОРЕ @ ...
 

Вот и все, ребята! read_html возвращает список всех

на странице в форме pandas.DataFrame , и, поскольку мы заглянули на страницу, мы знаем, что нужно просто взять первую, и мы запустились. !

Очевидно, что у нас есть несколько очень уродливых заголовков столбцов, но мы можем вернуться к этому позже.

Парсинг нескольких страниц

Если мы хотим автоматизировать парсинг нескольких страниц, нам нужно немного больше деталей. Теперь мы добавим вышеупомянутые запросов , который является базовым пакетом Python, который позволяет нам выполнять низкоуровневые запросы HTML/XML, и BeautifulSoup , который представляет собой пакет для манипулирования и сканирования необработанного HTML/XML.

(Кстати, парсинг веб-страниц — важный инструмент этического (белого) взлома — вот хороший набор онлайн-курсов по этому навыку, которые также знакомят с базовыми навыками Python.)

Обратите внимание, что схема именования PFR для игроков это немного странно. Заглушка Рассела Уилсона — W/WilsRu00 , а Антонио Брауна — B/BrowAn04 . Как мы собираемся выяснить, что все это такое, а затем просмотреть каждую страницу?

Посетите страницу Fantasy Leaders. Это список всех активных игроков в сезоне, а также их сезонные фэнтези-статистики, упорядоченные по общему количеству фэнтезийных очков. Обратите внимание, что каждый игрок в этой таблице имеет гиперссылку на свою индивидуальную страницу. Было бы неплохо, если бы мы могли просмотреть эту таблицу и записать URL-адрес каждого игрока? Мы не можем сделать это с нашими pandas.read_html трюк больше, потому что это удаляет гиперссылки на текст подписи. (То есть из Player он захватывает только Player . )

Но мы можем это сделать: давайте используем запросов для захвата необработанного HTML, затем BeautifulSoup , чтобы просканировать столбец «Имя» таблицы, записывая такие вещи, как гиперссылка, по мере продвижения.

Вот как получить первую таблицу как объект BeautifulSoup:

 from bs4 import BeautifulSoup
url = 'https://www.pro-football-reference.com'
год = 2018
r = request.get(url + '/years/' + str(year) + '/fantasy.htm')
суп = BeautifulSoup(r.content, 'html.parser')
parsed_table = суп.найти_все('таблица')[0]
 

Строка r = request.get(...) захватывает веб-страницу, и мы передаем необработанный HTML r.content в BeautifulSoup и делаем объект суп . Затем мы можем сделать что-то вроде find_all экземпляров тега 'table' и получить первый экземпляр с [0] .

Теперь, когда у нас есть необработанный HTML-код таблицы, хранящийся в parsed_table , вот как пройтись по строкам таблицы, захватив запись с именем игрока (которую вы можете заметить, просмотрев исходный код страницы, он удобно помечен атрибутом data-stat="player" ) и извлечение частей тега , которые нам нужны:

 # первые 2 строки являются заголовками столбцов, поэтому пропустите их с помощью [2:]
для i, строка в перечислении (parsed_table. find_all ('tr') [2:]):
    dat = row.find('td', attrs={'data-stat': 'игрок'})
    имя = dat.a.get_text()
    заглушка = dat.a.get('href')
    # ДАЛЕЕ: используйте `stub` для доступа к странице плеера
 

Эта заглушка содержит крупицу информации, за которой мы пришли. Теперь мы готовы объединить наш код в один огромный великолепный цикл:

 url = 'https://www.pro-football-reference.com'
год = 2018
макс.р = 300
    
# хватайте фэнтезийных игроков
r = request.get(url + '/years/' + str(year) + '/fantasy.htm')
суп = BeautifulSoup(r.content, 'html.parser')
parsed_table = суп.найти_все('таблица')[0]
дф = []
# первые 2 строки - заголовки столбцов
для i, строка в перечислении (parsed_table.find_all ('tr') [2:]):
    если я % 10 == 0: напечатать (я, конец = ' ')
    если я >= maxp:
        печать('\nЗавершено.')
        ломать
        
    пытаться:
        dat = row.find('td', attrs={'data-stat': 'игрок'})
        имя = dat.a.get_text()
        заглушка = dat.a.get('href')
        заглушка = заглушка[:-4] + '/фантазия/' + ул(год)
        pos = row. find('td', attrs={'data-stat': 'fantasy_pos'}).get_text()
        # получить статистику этого игрока
        tdf = pd.read_html(url + заглушка)[0]
        # избавиться от MultiIndex, просто оставить последнюю строку
        tdf.columns = tdf.columns.get_level_values ​​(-1)
        # исправляем колонку в гостях/дома
        tdf = tdf.rename(columns={'Безымянный: 4_level_2': 'Нет на месте'})
        tdf['Away'] = [1, если r=='@' else 0 для r в tdf['Away']]
        # удалить все промежуточные характеристики
        tdf = tdf.iloc[:,[1,2,3,4,5,-3]]
        
        # удалить строку "Всего"
        tdf = tdf.query('Дата!= "Всего"')
        
        # добавить другую информацию
        tdf['Имя'] = имя
        tdf['Позиция'] = позиция
        tdf['Сезон'] = год
        df.append(tdf)
    кроме:
        проходить
    
df = pd.concat (df)
дф.голова()
 
 G# Дата Tm Away Opp FantPt Имя Должность Сезон
0 1.0 10.09.2018 LAR 1 ДУБ 20.7 Тодд Герли РБ 2018
1 2.0 2018-09-16 LAR 0 ARI 29.3 Тодд Герли РБ 2018
2 3. 0 23.09.2018 LAR 0 LAC 19.6 Тодд Герли РБ 2018
3 4.0 27.09.2018 ЛАР 0 МИН 21.6 Тодд Герли РБ 2018
4 5.0 07.10.2018 LAR 1 SEA 29.3 Тодд Герли РБ 2018
 

, и поскольку это, вероятно, займет несколько минут (в зависимости от настроек maxp и вашего интернет-соединения), я рекомендую сохранить df в CSV:

 df.to_csv('fantasy2018.csv')
 

График среднего и дисперсии

Итак, теперь вы можете легко получить траектории производительности одного или нескольких игроков за сезон и построить их, если хотите:

 (df.query('Name == "Saquon Barkley" ')
    .plot('Дата', 'FantPt'))
 

Чтобы лучше понять данные, давайте взглянем на сводную статистику. Моя первая мысль — сократить траекторию фантазии каждого игрока до 9 баллов.0115 означает и дисперсию . Идеальный игрок имеет высокое среднее/среднее общее количество очков и не слишком сильно отклоняется от него. У игрока типа «бум или спад», возможно, среднее значение от среднего до высокого, но чрезвычайно высокая дисперсия.

Вот код (грубая сила):

 fig, ax = plt.subplots(1,4, sharey=True, figsize=(15,4))
столбцы = ['к', 'с', 'г', 'б']
для i, pos в enumerate(["QB", "RB", "WR", "TE"]):
т = (дф
.query('Позиция == @pos')
.groupby('Имя')
.agg({'FantPt': ['среднее', 'стандартное'],
'Позиция': 'мин'}))
ax[i].scatter(t[('FantPt','среднее')], t[('FantPt', 'std')],
c=столбцы[i], s=50, альфа=0,5, метка=поз.)
ax[i].set(xlabel='Среднее значение', title=pos)
# пометить некоторые выбросы
ax[0].annotate('П. Махоумс', xy=(26, 6.76), xytext=(16, 2),
arrowprops={'facecolor':'черный', 'ширина':0,1, 'усадка':0,08})
ax[1].annotate('Т. Герли', xy=(22.36, 8.1), xytext=(15, 2),
arrowprops={'facecolor':'черный', 'ширина':0,1, 'усадка':0,08})
ax[2].annotate('Д. Адамс', xy=(14.57, 4.2), xytext=(9, 2),
arrowprops={'лицоцвет':'черный', 'ширина':0,1, 'сжать':0,1})
ax[3].annotate('Т. Келче', xy=(11.97, 7.5), xytext=(9, 2),
arrowprops={'лицоцвет':'черный', 'ширина':0,1, 'сжать':0,1})

топор[0].

Адрес: Великий Новгород, площадь Победы-Софийская, дом 1
Электронная почта: [email protected] Телефон/ факс приёмной
Законодательная карта сайта