
本教程旨在解决从NBA官网动态页面爬取选秀体测数据时遇到的挑战。针对传统HTML解析工具难以获取JavaScript动态加载内容的问题,文章将深入探讨如何通过分析网络请求,直接调用NBA官方API接口来获取结构化的JSON数据,并利用`pandas`库将其高效转换为易于处理的数据帧,从而实现稳定且高效的数据采集。
在尝试从如NBA官网这类现代网站上爬取数据时,开发者经常会遇到一个常见问题:即使页面在浏览器中正常显示表格数据,使用requests和BeautifulSoup等工具直接请求页面HTML内容时,却无法找到目标数据。这通常是因为这些数据并非直接嵌入在初始HTML中,而是通过JavaScript在页面加载完成后异步从后端API获取并渲染到页面上的。
例如,对于NBA选秀体测数据页面(https://www.nba.com/stats/draft/combine-anthro),如果直接使用BeautifulSoup去查找<table>标签,很可能一无所获。这是因为页面上的数据表格是在浏览器端执行JavaScript代码后,通过AJAX请求从一个独立的API接口获取JSON数据,然后动态构建出来的。
要解决这类问题,最有效的方法是绕过前端渲染过程,直接与后端数据源进行交互。这通常涉及到以下步骤:
立即学习“Python免费学习笔记(深入)”;
对于NBA选秀体测数据,通过开发者工具分析发现,页面数据实际上来源于一个名为draftcombineplayeranthro的API接口。
一旦确定了API接口及其调用方式,我们就可以使用Python的requests库来模拟浏览器请求,直接获取JSON数据。
首先,我们需要导入requests库来发送HTTP请求,以及pandas库来处理和组织获取到的数据。
import requests import pandas as pd
NBA的统计API通常需要特定的参数来过滤数据,例如LeagueID和SeasonYear。同时,为了模拟真实浏览器行为,避免被服务器识别为爬虫并拒绝访问,我们还需要设置一些HTTP请求头,如Referer和User-Agent。
# API接口URL
url = "https://stats.nba.com/stats/draftcombineplayeranthro"
# 请求参数,用于指定联赛ID和赛季年份
# LeagueID: "00" 通常代表NBA
# SeasonYear: 例如 "2022-23" 表示2022-2023赛季
payload = {
"LeagueID": "00",
"SeasonYear": "2022-23" # 根据需要修改赛季年份
}
# 请求头,模拟浏览器行为
headers = {
"Referer": "https://www.nba.com/", # 模拟请求来源
"User-Agent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36" # 模拟用户代理
}注意: User-Agent字符串应尽可能使用最新的浏览器版本,可以从你的浏览器开发者工具中复制。
使用requests.get()方法发送GET请求,并通过params参数传递payload,通过headers参数传递headers。API返回的数据是JSON格式,可以直接通过.json()方法解析为Python字典。
# 发送GET请求并获取JSON响应 response = requests.get(url, params=payload, headers=headers) response.raise_for_status() # 检查请求是否成功(状态码200) data = response.json()
NBA统计API的JSON响应通常包含一个resultSets列表,其中每个元素代表一个数据集。每个数据集又包含headers(列名)和rowSet(数据行)。我们可以利用这些信息,方便地将数据转换为pandas.DataFrame。
# 从JSON数据中提取列名和数据行 # resultSets[0]通常是第一个(或唯一)数据集 columns = data["resultSets"][0]["headers"] rows = data["resultSets"][0]["rowSet"] # 创建DataFrame df = pd.DataFrame(rows, columns=columns)
import requests
import pandas as pd
def get_nba_combine_anthro_data(season_year="2022-23"):
"""
从NBA官方API获取指定赛季的选秀体测数据。
Args:
season_year (str): 赛季年份,例如 "2022-23"。
Returns:
pd.DataFrame: 包含选秀体测数据的DataFrame。
如果获取失败,则返回None。
"""
url = "https://stats.nba.com/stats/draftcombineplayeranthro"
payload = {
"LeagueID": "00",
"SeasonYear": season_year
}
# 推荐使用最新的User-Agent字符串
headers = {
"Referer": "https://www.nba.com/",
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36"
}
try:
response = requests.get(url, params=payload, headers=headers, timeout=10)
response.raise_for_status() # 如果状态码不是200,则抛出HTTPError异常
data = response.json()
columns = data["resultSets"][0]["headers"]
rows = data["resultSets"][0]["rowSet"]
df = pd.DataFrame(rows, columns=columns)
return df
except requests.exceptions.RequestException as e:
print(f"请求失败: {e}")
return None
except KeyError as e:
print(f"JSON解析错误,可能API响应结构发生变化: {e}")
return None
# 调用函数获取数据
nba_combine_df = get_nba_combine_anthro_data(season_year="2022-23")
if nba_combine_df is not None:
print("成功获取NBA选秀体测数据:")
print(nba_combine_df.head())
print(f"\n数据总行数: {len(nba_combine_df)}")
print(f"数据总列数: {len(nba_combine_df.columns)}")运行上述代码,你将得到一个包含NBA选秀体测数据的pandas.DataFrame,其部分内容如下所示:
成功获取NBA选秀体测数据: TEMP_PLAYER_ID PLAYER_ID FIRST_NAME ... BODY_FAT_PCT HAND_LENGTH HAND_WIDTH 0 1630534 1630534 Ochai ... 5.40 8.75 9.50 1 1631116 1631116 Patrick ... 8.90 8.75 9.50 2 1631094 1631094 Paolo ... NaN NaN NaN 3 1631109 1631109 Mark ... 5.40 9.00 9.75 4 1630592 1630592 Jalen ... NaN NaN NaN [5 rows x 18 columns] 数据总行数: 83 数据总列数: 18
通过直接调用后端API,我们能够高效且稳定地获取NBA选秀体测数据,避免了前端JavaScript渲染带来的复杂性。这种方法不仅适用于NBA官网,也适用于许多其他采用动态加载内容的网站,是现代网络数据采集的重要技术之一。
以上就是Python进阶:高效爬取NBA选秀体测数据的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号