一、前言:为什么需要爬取 NBA 数据源?
对于 NBA 数据分析爱好者而言,数据源的获取主要有两种方式:一是借助 NBA 官方提供的 API 接口,二是通过网页爬取的方式获取公开数据。前者虽然数据精准、格式规范,但存在接口调用限制、部分数据收费等问题,对于非专业开发者不够友好;后者则针对公开的 NBA 静态网页(如 NBA 中文官网、篮球数据网站等),通过解析网页结构提取数据,门槛低、自由度高,适合入门学习者。
BeautifulSoup 是 Python 中用于解析 HTML 和 XML 文档的第三方库,与 Requests 库配合使用,能够快速抓取网页内容并提取关键数据,无需复杂的正则表达式,上手难度极低。本文将以 NBA 中文官网的球员数据为爬取目标,带领读者掌握 BeautifulSoup 的核心用法,同时完成 NBA 数据源的采集,为后续的得分分析、球员效率分析、球队战绩分析等工作提供数据支撑。
本文爬取的核心目标的是:NBA 常规赛球员的基础数据(姓名、位置、出场次数、得分、篮板、助攻等),爬取对象为 NBA 中文官网的公开数据页面,全程采用 Python 3.x 环境,核心依赖库为 Requests(请求网页)和 BeautifulSoup4(解析网页)。
二、环境搭建:必备工具与依赖库安装
在开始爬取工作前,需要先完成 Python 环境的搭建以及相关依赖库的安装。本文采用 Python 3.8 版本(兼容 3.6 及以上所有版本),读者可根据自身电脑系统(Windows、Mac、Linux)下载对应的 Python 安装包,安装过程中勾选“Add Python to PATH”,确保后续能够正常使用命令行调用 Python。
2.1 核心依赖库说明
本次爬取工作需要用到两个核心依赖库,分别是:
-
Requests:用于向目标网页发送 HTTP 请求,获取网页的 HTML 源代码。它是 Python 中最常用的网络请求库,语法简洁,支持 GET、POST 等多种请求方式,能够轻松应对静态网页的请求需求。
-
BeautifulSoup4(简称 bs4):用于解析 Requests 获取到的 HTML 源代码,提取网页中的目标数据。它能够将复杂的 HTML 文档转化为树形结构,提供简单易用的 API,让开发者能够快速定位并提取所需内容,无需编写复杂的正则表达式。
三、网页分析:定位 NBA 数据所在位置
网页爬取的核心是“找到数据所在的 HTML 位置”,在编写代码前,需要先分析目标网页的结构,确定我们需要的 NBA 球员数据藏在 HTML 代码的哪个部分。本文的爬取目标是 NBA 中文官网的“球员数据”页面,具体步骤如下:
3.1 确定目标网页地址
打开浏览器(推荐 Chrome 或 Edge),访问 NBA 中文官网的球员数据页面,本次爬取的页面地址为:china.nba.com/stats/playe…。该页面展示了 NBA 所有球员的常规赛基础数据,支持按得分、篮板等维度排序,数据公开且结构清晰,适合作为爬取目标。
3.2 分析网页结构,定位数据位置
在目标网页上,右键点击“检查”(或按 F12 键),打开浏览器的开发者工具,切换到“Elements”(元素)选项卡,即可查看网页的 HTML 源代码。我们需要找到包含球员数据的 HTML 标签,具体操作如下:
-
在开发者工具中,点击左上角的“选择元素”按钮(箭头图标),然后点击网页中的球员数据表格,即可在 HTML 源代码中定位到表格对应的标签。
-
观察 HTML 结构,发现球员数据全部放在一个
标签中,该标签的 class 属性为“stats-table”,这是我们定位表格的核心标识。
-
表格内部,
标签包含表头信息(姓名、位置、出场次数、得分等), 标签包含所有球员的具体数据,每一行球员数据对应一个 标签,每一个单元格对应一个 | 标签。
通过以上分析,我们可以确定:只需定位到 class 为“stats-table”的 标签,然后提取 标签下的所有 标签,再逐一解析每个 标签下的 标签,提取所有 标签,提取所有 标签(每一行对应一名球员),然后逐一解析每个 标签下的 |
| 标签内容,即可获取所有球员的基础数据。
需要注意的是,部分网页会采用动态加载技术(如 JavaScript 渲染),但本次爬取的 NBA 中文官网球员数据页面为静态网页,HTML 源代码中直接包含所有球员数据,无需处理动态加载问题,适合入门练习。
四、代码实现:完整爬取流程与解析
结合前面的环境搭建和网页分析,我们接下来编写完整的爬取代码,全程分为 5 个步骤:发送 HTTP 请求获取网页源代码、使用 BeautifulSoup 解析网页、提取表头信息、提取球员数据、保存数据到本地(CSV 格式,方便后续数据分析)。
4.1 完整代码(可直接复制运行)
import requests
from bs4 import BeautifulSoup
import csv
url = "https://china.nba.com/stats/players/"
headers = {
"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, headers=headers)
response.raise_for_status()
response.encoding = response.apparent_encoding
html = response.text
print("网页请求成功,已获取 HTML 源代码")
except Exception as e:
print(f"网页请求失败,错误信息:{e}")
exit()
soup = BeautifulSoup(html, "lxml")
table = soup.find("table", class_="stats-table")
thead = table.find("thead")
th_list = thead.find_all("th")
headers = []
for th in th_list:
header = th.get_text(strip=True)
headers.append(header)
print("表头信息:", headers)
tbody = table.find("tbody")
tr_list = tbody.find_all("tr")
player_data_list = []
for tr in tr_list:
td_list = tr.find_all("td")
player_data = []
for td in td_list:
data = td.get_text(strip=True)
player_data.append(data)
player_data_list.append(player_data)
print(f"共爬取到 {len(player_data_list)} 名球员的数据")
print("前 5 名球员数据:", player_data_list[:5])
csv_path = "NBA球员数据.csv"
try:
with open(csv_path, "w", newline="", encoding="utf-8-sig") as f:
writer = csv.writer(f)
writer.writerow(headers)
writer.writerows(player_data_list)
print(f"数据保存成功,文件路径:{csv_path}")
except Exception as e:
print(f"数据保存失败,错误信息:{e}")
4.2 代码分步解析
步骤 1:导入依赖库
代码开头导入了三个所需库:requests 用于发送网络请求,BeautifulSoup 用于解析 HTML,csv 用于将数据保存为 CSV 格式。其中,csv 是 Python 内置库,无需额外安装,直接导入即可使用。
步骤 2:发送 HTTP 请求,获取网页源代码
首先定义目标网页的 URL,然后添加请求头(User-Agent),模拟浏览器访问——这是避免被网站反爬的基础操作。很多网站会检测请求的 User-Agent,若发现是爬虫程序(默认 User-Agent 为 Python-requests),会拒绝提供数据,因此需要设置浏览器的 User-Agent。
使用 try-except 语句包裹请求代码,用于捕获请求过程中可能出现的错误(如网络中断、网页无法访问等),提高代码的健壮性。请求成功后,设置编码格式为 response.apparent_encoding,避免中文乱码,然后获取网页的 HTML 源代码。
步骤 3:使用 BeautifulSoup 解析 HTML
将获取到的 HTML 源代码传入 BeautifulSoup,指定解析器为 lxml——lxml 解析器解析速度快、兼容性好,是 BeautifulSoup 最常用的解析器。若未安装 lxml 库,执行 pip install lxml 即可。
解析后得到 soup 对象,通过 soup 对象的 find() 和 find_all() 方法,即可定位到目标 HTML 标签,提取所需数据。
步骤 4:提取表头和球员数据
-
提取表头:通过 soup.find("table", class_="stats-table") 定位到球员数据表格(class 为 stats-table),然后找到 | 标签的文本,作为 CSV 文件的表头。
-
提取球员数据:找到 |
|---|
|
| 标签文本,将每一名球员的数据存储为列表,最终汇总到 player_data_list 中。
代码中使用 get_text(strip=True) 方法提取标签文本,strip=True 表示去除文本前后的空格和换行符,确保数据的整洁性。
步骤 5:保存数据到 CSV 文件
使用 Python 内置的 csv 库,将表头和球员数据写入 CSV 文件。open() 函数中,encoding="utf-8-sig" 用于避免中文乱码(Windows 系统默认编码为 GBK,utf-8-sig 可兼容 Windows 和 Mac 系统),newline="" 用于避免 CSV 文件中出现多余的空行。
保存成功后,可在当前代码所在目录下找到“NBA球员数据.csv”文件,打开后即可看到所有爬取的球员数据,后续可直接用于 Python 数据分析(如使用 Pandas 读取 CSV 文件)。
五、常见问题与解决方案
在实际爬取过程中,可能会遇到一些问题,导致爬取失败或数据异常,以下是几种常见问题及对应的解决方案,帮助读者顺利完成爬取工作。
5.1 问题 1:网页请求失败,提示“403 Forbidden”
原因:网站检测到请求不是来自浏览器,拒绝提供数据(反爬机制)。
解决方案:完善请求头,除了 User-Agent,还可以添加 Referer(表示请求来源),代理IP,修改后的 headers 如下:
import requests
proxyHost = "www.16yun.cn"
proxyPort = "5445"
proxyUser = "16QMSOML"
proxyPass = "280651"
proxies = {
"http": f"http://{proxyUser}:{proxyPass}@{proxyHost}:{proxyPort}",
"https": f"https://{proxyUser}:{proxyPass}@{proxyHost}:{proxyPort}"
}
headers = {
"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",
"Referer": "https://china.nba.com/"
}
if __name__ == "__main__":
try:
url = "https://china.nba.com/"
response = requests.get(
url=url,
headers=headers,
proxies=proxies,
timeout=10
)
response.raise_for_status()
print(f"请求成功,状态码:{response.status_code}")
print(f"响应内容长度:{len(response.text)} 字符")
except requests.exceptions.RequestException as e:
print(f"请求失败:{e}")
5.2 问题 2:解析网页时,提示“AttributeError: 'NoneType' object has no attribute 'find'”
原因:未找到目标 HTML 标签(如 table 标签),可能是网页结构发生变化,或请求头未设置导致获取的 HTML 源代码异常。
解决方案:1. 重新检查网页结构,确认目标标签的 class 或 id 是否发生变化;2. 验证请求是否成功,打印 html 变量查看获取的 HTML 源代码是否正常;3. 更换解析器(如将 lxml 改为 html.parser)。
5.3 问题 3:数据保存后,中文乱码
原因:编码格式设置错误,Windows 系统默认编码为 GBK,若使用 utf-8 编码保存,可能会出现乱码。
解决方案:将 open() 函数中的 encoding 设置为 utf-8-sig,而非 utf-8,utf-8-sig 会自动添加 BOM 头,兼容 Windows 系统的 Excel 打开。
5.4 问题 4:爬取的数据不完整
原因:NBA 官网的球员数据页面可能分页展示,本文代码仅爬取第一页数据,若需要获取所有球员数据,需处理分页逻辑。
解决方案:分析分页 URL 的规律,通过循环遍历所有分页,逐一爬取每一页的数据,然后汇总保存。例如,分页 URL 可能为 china.nba.com/stats/playe… page 参数的值,实现多页爬取。
六、延伸:爬取数据后的数据分析方向
本文完成的 NBA 数据源爬取,是数据分析的前置步骤,获取数据后,可借助 Python 的 Pandas、Matplotlib、Seaborn 等库,开展以下数据分析工作:
-
球员得分分析:统计球员的场均得分、总得分,筛选得分榜前 10 名球员,绘制得分分布直方图,分析联盟得分整体情况。
-
球员效率分析:结合篮板、助攻、抢断、盖帽等数据,计算球员的效率值(PER),评估球员的综合表现。
-
球队数据汇总:按球队分组,统计各球队的场均得分、场均篮板、胜率等数据,分析不同球队的实力差异。
-
数据可视化:通过 Matplotlib 绘制折线图、柱状图、热力图等,直观展示球员数据之间的关联(如得分与篮板的相关性)。
例如,使用 Pandas 读取 CSV 文件的代码如下:
import pandas as pd
df = pd.read_csv("NBA球员数据.csv")
print(df.head())
print(df.info())
top10_score = df.sort_values(by="场均得分", ascending=False).head(10)
print("场均得分前 10 名:")
print(top10_score[["姓名", "球队", "场均得分"]])
七、总结
本文以“Python 数据分析前置”为核心,完整讲解了使用 BeautifulSoup 爬取 NBA 数据源的全流程,从环境搭建、网页分析,到代码实现、问题排查,每一步都兼顾专业性和实用性,适合 Python 入门学习者上手练习。
通过本文的学习,读者不仅能够掌握 BeautifulSoup 和 Requests 库的核心用法,成功获取 NBA 球员数据,更能理解“数据爬取是数据分析的基础”这一核心逻辑——只有掌握了数据源的获取方法,才能后续开展更深入的数据分析工作。 |
|