比较足球运动员大学母校与NFL幻想足球总输出的Python Webscraping方法

2024-04-27 15:35:51 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在寻找一个数据科学项目,在该项目中,我将能够总结球员们就读的大学的梦幻足球分数(例如,阿拉巴马州有56名NFL活跃球员,因此我将通过一个数据库,将他们所有的梦幻分数加起来,与其他学校进行比较)

我在看网站: https://fantasydata.com/nfl/fantasy-football-leaders?season=2020&seasontype=1&scope=1&subscope=1&aggregatescope=1&range=3

我打算用漂亮的汤来刮去一排排球员和统计数据,最终是梦幻足球分数

然而,我很难弄清楚如何提取球员的大学母校。为此,我必须:

  • 单击每个“玩家”名称
  • 将数百名NFL球员的每一个侧面都划一行“大学”
  • 将所有这些信息放在它自己的列中

有什么建议吗


Tags: 数据项目httpscom数据库网站科学分数
2条回答

我同意,如果他们在那里,API是一条路要走。我的第二个“go to”是pandas{}(它在引擎盖下使用BeautifulSoup解析<table>标记。这里有一个替代解决方案,使用ESPNs api获取团队花名册链接,然后使用pandas从每个链接中提取表。省去了必须迭代每个玩家才能获取学院的麻烦(据我所知,nfl.com以前有一个api返回所有玩家,但现在不再公开了)

代码:

import requests
import pandas as pd
    
url = 'https://site.web.api.espn.com/apis/common/v3/sports/football/nfl/athletes/101'

all_teams = []
roster_links = []
for i in range(1,35):
    url = 'http://site.api.espn.com/apis/site/v2/sports/football/nfl/teams/{teamId}'.format(teamId=i)
    jsonData = requests.get(url).json()
    print (jsonData['team']['displayName'])
    for link in jsonData['team']['links']:
        if link['text'] == 'Roster':
            roster_links.append(link['href'])
            break
    
for link in roster_links:
    print (link)
    tables = pd.read_html(link)
    df = pd.concat(tables).drop('Unnamed: 0',axis=1)
    df['Jersey'] = df['Name'].str.replace("([A-Za-z.' ]+)", '')
    df['Name'] = df['Name'].str.extract("([A-Za-z.' ]+)")
    all_teams.append(df)

final_df = pd.concat(all_teams).reset_index(drop=True)

输出:

print (final_df)
                  Name POS  Age      HT       WT Exp           College Jersey
0            Matt Ryan  QB   35   6' 4"  217 lbs  13    Boston College      2
1          Matt Schaub  QB   39   6' 6"  245 lbs  17          Virginia      8
2       Todd Gurley II  RB   26   6' 1"  224 lbs   6           Georgia     21
3           Brian Hill  RB   25   6' 1"  219 lbs   4           Wyoming     23
4       Qadree Ollison  RB   24   6' 1"  232 lbs   2        Pittsburgh     30
               ...  ..  ...     ...      ...  ..               ...    ...
1772    Jonathan Owens   S   25  5' 11"  210 lbs   2  Missouri Western     36
1773       Justin Reid   S   23   6' 1"  203 lbs   3          Stanford     20
1774  Ka'imi Fairbairn  PK   26   6' 0"  183 lbs   5              UCLA      7
1775       Bryan Anger   P   32   6' 3"  205 lbs   9        California      9
1776         Jon Weeks  LS   34  5' 10"  242 lbs  11            Baylor     46

[1777 rows x 8 columns]

不需要Selenium或其他无头自动化浏览器。那太过分了

如果查看浏览器的网络流量,您会注意到浏览器向这个RESTAPI端点发出POST请求:https://fantasydata.com/NFL_FantasyStats/FantasyStats_Read

如果POST请求格式正确,API将使用JSON响应,其中包含关于每个玩家的信息。通常,这些信息将用于使用JavaScript异步填充DOM。那里有很多信息,但不幸的是,学院信息不是JSON响应的一部分。但是,有一个字段PlayerUrlString,它是给定玩家个人资料页面的相对URL,其中确实包含学院名称。因此:

  • 向API发出POST请求以获取所有玩家的信息

对于响应JSON中的每个播放器:

  • 访问该玩家的个人资料
  • 使用BeautifulSoup从当前列表中提取学院名称 球员简介

代码:

def main():

    import requests
    from bs4 import BeautifulSoup

    url = "https://fantasydata.com/NFL_FantasyStats/FantasyStats_Read"

    data = {
        "sort": "FantasyPoints-desc",
        "pageSize": "50",
        "filters.season": "2020",
        "filters.seasontype": "1",
        "filters.scope": "1",
        "filters.subscope": "1",
        "filters.aggregatescope": "1",
        "filters.range": "3",
    }

    response = requests.post(url, data=data)
    response.raise_for_status()

    players = response.json()["Data"]
    for player in players:
        url = "https://fantasydata.com" + player["PlayerUrlString"]

        response = requests.get(url)
        response.raise_for_status()

        soup = BeautifulSoup(response.content, "html.parser")

        college = soup.find("dl", {"class": "dl-horizontal"}).findAll("dd")[-1].text.strip()

        print(player["Name"] + " went to " + college)

    return 0


if __name__ == "__main__":
    import sys
    sys.exit(main())

输出:

Patrick Mahomes went to Texas Tech
Kyler Murray went to Oklahoma
Aaron Rodgers went to California
Russell Wilson went to Wisconsin
Josh Allen went to Wyoming
Deshaun Watson went to Clemson
Ryan Tannehill went to Texas A&M
Lamar Jackson went to Louisville
Dalvin Cook went to Florida State
...

您还可以在data字典中编辑pageSizePOST参数。50对应于JSON响应中前50个参与者的信息(根据其他POST参数设置的过滤器)。更改此值将在JSON响应中产生更多或更少的参与者

相关问题 更多 >