爬取和分析NBA球員排名及各項數據


一、選題的背景

NBA受到世界各地極大多數人的喜愛,不分年齡,學生、員工、勞動工人等社會各界都有熱愛籃球的人,也有各自喜歡信仰的球星,在NBA中國官方網站里他們更好的了解和清楚自己喜愛的球星和其它聯盟里的球星的一些數據對比,知道他們近期的一些起伏和爆發,本次爬蟲建立在這基礎上,通過對網頁數據的提取並進行可視化對比,更好地了解聯盟里球員的排名和其余各項數據之間的關系來分析對球隊的貢獻好與壞。

二、設計方案

1.爬蟲名稱:爬取NBA球員排名及各項數據

2.爬取內容:爬取NBA球員排名、場均得分、各項命中率等

3.方案概述:訪問網頁得到狀態碼200,分析網頁源代碼,找出所需要的的標簽,逐個提取標簽保存到相同路徑csv文件中,讀取該文件,進行數據清洗,數據模型分析,數據可視化處理,繪制排名與其余幾項數據的關系圖。

技術難點:

1.在爬取網頁數據,提取數據成csv文件時,由於數據較為雜亂。

2. 做數據分析,即求回歸系數,因為標題是文字,無法與數字作比較,需要把標題這一列刪除才可。由於不明原因,輸出結果經常會顯示超出列表范圍。

三、主題頁面的結構特征分析

首先,本次爬蟲爬取NBA中國官方網站(https://china.nba.com/statistics/)球員排名及各項數據

1.頁面信息

在頁面中找到Network(網絡)之后,再找到XHR之后,刷新頁面,獲取到該網頁的一些數據。找到保存數據的json文件

 

2.對json文件進行數據提取

在上一步查詢的結果數據中篩選json文件找到正確的json文件之后,查詢預覽的結果,可以看到與需要爬取的信息相符,就是我們需要的庫。

 

  確定json文件信息是正確且需要的之后,再查詢標頭,找到user—URL。

之后開始我們對NBA中國官方網站球員數據的抓包。

四、網絡爬蟲程序設計

1.數據爬取與采集

#爬取網頁數據

#提取數據
import requests
from bs4 import BeautifulSoup
import json
import numpy as np 
#
url='https://china.nba.cn/stats2/league/playerstats.json?conference=All&country=All&individual=All&locale=zh_CN&pageIndex=0&position=All&qualified=false&season=2021&seasonType=2&split=All+Team&statType=points&team=All&total=perGame'
#
def getHTMLText(url,timeout=30):
    try:
        r=requests.get(url,timeout=30) # 
        r.raise_for_status()
        r.encoding=r.apparent_encoding
        return r.text
    except:
        return'產生異常'
    
#html.parser表示用BeautifulSoup庫解析網頁
html=getHTMLText(url)
soup=BeautifulSoup(html,'html.parser')
print(soup.prettify())

 

結果如下:

 

#采集數據

#創建空表
pointsPg_list=[]
assistsPg_list=[]
rebsPg_list=[]
name_list=[]
data1=[]
tppct=[]
ftpct=[]
fgpct=[]
stealsPg_list=[]
blocksPg_list=[]
offRebsPg_list=[]
defRebsPg_list=[]
rank=[]
html=getHTMLText(url)
data=json.loads(html)
a=data['payload']['players']
data1.append(name_list)
data1.append(assistsPg_list)
b=1
for i in a:   
    rank.append(b)
    name_list.append(i['playerProfile']['displayName'])
    pointsPg_list.append(i['statAverage'][ 'pointsPg'])
    rebsPg_list.append(i['statAverage'][ 'rebsPg'])
    assistsPg_list.append(i['statAverage'][ 'assistsPg'])
    stealsPg_list.append(i['statAverage'][ 'stealsPg'])
    blocksPg_list.append(i['statAverage'][ 'blocksPg'])
    offRebsPg_list.append(i['statAverage'][ 'offRebsPg'])
    defRebsPg_list.append(i['statAverage'][ 'defRebsPg'])
    tppct.append(i['statAverage']['tppct'])
    ftpct.append(i['statAverage']['ftpct'])
    fgpct.append(i['statAverage']['fgpct'])
    b=b+1
list_1=['排名']

#導出球員的各項數據
import pandas as pd
df=pd.DataFrame(columns=list_1)
df['排名']=rank
df['NAME']=name_list
df['場均得分']=pointsPg_list
df['場均籃板']=rebsPg_list
df['場均助攻']=assistsPg_list
df['投籃命中率']=fgpct
df['三分命中率']=tppct
df['罰球命中率']=ftpct
df['進攻效率']=offRebsPg_list
df['防守效率']=defRebsPg_list
df['場均搶斷']=stealsPg_list
df['場均蓋帽']=blocksPg_list
df=df.drop_duplicates()
df

 

結果如下:

 #保存數據

#將dataframe寫入csv
df.to_csv('D:/Python/NBA數據.csv',index=False)
df.to_csv('D:/Python/NBA.csv',index=False)

2.對數據進行清洗和處理

 #檢查重復值

#檢查並顯示重復值
print(df.duplicated())

 

 #刪除重復值

#刪除重復值
df = df.drop_duplicates()
df.head(

 

 #檢查是否有空值

#檢查是否有空值
print(df['NAME'].isnull().value_counts())

 

#異常值處理

#異常值處理
df.describe()

 

 #查看統計信息

#查看統計信息
print(df.describe()

 

 

3、數據分析與可視化(例如:數據柱形圖、折線圖圖、散點圖、回歸圖、分布圖)

 #數據可視化

#繪制柱狀圖

#繪制柱狀圖
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
plt.rcParams['font.sans-serif']=['SimHei']
plt.bar(df.排名, df.投籃命中率, color='b')
plt.xlabel("排名")
plt.ylabel("投籃命中率")
plt.title('排名與投籃命中率柱狀圖')
plt.show()

結果:

 #繪制散點圖

#繪制散點圖
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
plt.rcParams['font.sans-serif']=['SimHei']
plt.rcParams['axes.unicode_minus'] = False   # 用來正常顯示負號
size=30
plt.scatter(df.排名, df.場均得分,size, color='b',alpha=0.6,marker='o')
plt.xlabel("排名")
plt.ylabel("場均得分")
plt.title('排名與場均得分柱狀圖')
plt.show()

結果:

 

#繪制堆疊圖

#繪制罰球命中率與排名圖
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
plt.rcParams['font.sans-serif']=['SimHei']
plt.rcParams['axes.unicode_minus'] = False   # 用來正常顯示負號
plt.stackplot(df.排名, df.罰球命中率, color=['b',])
plt.xlabel("排名")
plt.ylabel("罰球命中率")
plt.title('排名與罰球命中率堆疊圖')
plt.show()

結果:

 #繪制折線圖

#繪制折線圖
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
plt.rcParams['font.sans-serif']=['SimHei']
plt.rcParams['axes.unicode_minus'] = False
plt.plot(df.排名, df.三分命中率, color='b')
plt.xlabel("排名")
plt.ylabel("三分命中率")
plt.title('排名與三分命中率折線圖')
plt.show()

結果:

 

4.數據處理分析

#求回歸系數

#求取回歸系數
from sklearn.linear_model import LinearRegression
X=df.drop('NAME',axis=1)
predict_model=LinearRegression()
predict_model.fit(X,df['排名'])
print('回歸系數為:',predict_model.coef_)

結果求得:

#繪制回歸圖

#繪制回歸圖
import seaborn as sns
import matplotlib.pyplot as plt
plt.rcParams['font.sans-serif']=['SimHei']#用來正常顯示中文標簽
X=df.drop('NAME',axis=1)
sns.regplot(df['排名'],df['進攻效率'])
sns.regplot(df['排名'],df['防守效率'])
plt.title('排名與進攻、防守效率圖')

結果:

 

通過以上的分析,我們可以發現在排名與一些其他數據的比較之中,呈現出起伏的變化,可以得知一些場均得分排在前面的球員,在各項命中率,防守、進攻效率以及場均能得到的搶斷和防守並沒有比排在他們之后的一些球員高。從現實上的比賽來看,出手數對得分起到了一定的影響,導致場均得分較低。

 

5.根據數據之間的關系,分析兩個變量之間的相關系數,畫出散點圖,並建立變量之間的回歸方程(一元或多元)。

#選擇場均得分以及進攻效率,防守效率和場均搶斷四個特征變量,用最小二乘法分析兩個變量間的二次擬合方程和擬合曲線

#繪制擬合曲線

1.進攻效率與場均得分

#繪制擬合曲線
import matplotlib.pyplot as plt
import matplotlib
import numpy as np
import scipy.optimize as opt
import csv
x0=df['進攻效率']
y0=df['場均得分']
def func(x,c):
    k,a=c
    return k*x+a
def errfc(c,x,y):
    return y-func(x,c)
c0=(100,20)
#調用擬合曲線
print(opt.leastsq(errfc,c0,args=(x0,y0)))
#s設置畫布
chinese=matplotlib.font_manager.FontProperties(fname='C:\Windows\Fonts\simsun.ttc')  

plt.plot(x0,y0,"o",label=u"進攻效率")

plt.plot(x0,func(x0,opt.leastsq(errfc,c0,args=(x0,y0))[0]),label=u"場均得分")
plt.title('進攻效率與場均得分擬合曲線圖')
plt.legend(loc=3,prop=chinese)

plt.show()

結果:

 2.防守效率與場均搶斷

#繪制擬合曲線
import matplotlib.pyplot as plt
import matplotlib
import numpy as np
import scipy.optimize as opt
import csv
x0=df['防守效率']
y0=df['場均搶斷']
#
def func(x,c):
    k,a=c
    return k*x+a
def errfc(c,x,y):
    return y-func(x,c)
c0=(100,20)
#調用擬合曲線
print(opt.leastsq(errfc,c0,args=(x0,y0)))
#s設置畫布
chinese=matplotlib.font_manager.FontProperties(fname='C:\Windows\Fonts\simsun.ttc')  

plt.plot(x0,y0,"o",label=u"防守效率")

plt.plot(x0,func(x0,opt.leastsq(errfc,c0,args=(x0,y0))[0]),label=u"場均搶斷")
plt.title('防守效率與場均搶斷擬合曲線圖')
plt.legend(loc=3,prop=chinese)

plt.show()

結果:

 6、數據持久化

#數據持久化
df = pd.DataFrame(df,columns=['排名','NAME','場均得分','場均籃板','場均助攻','投籃命中率','罰球命中率','三分命中率','進攻效率','防守效率','場均搶斷','場均蓋帽'])
df.to_csv('NBA.csv',encoding = 'gbk') #保存文件,數據持久化

 

7、將以上各部分的代碼匯總,附上完整程序代碼

  1 #提取數據
  2 import requests
  3 from bs4 import BeautifulSoup
  4 import json
  5 #
  6 url='https://china.nba.cn/stats2/league/playerstats.json?conference=All&country=All&individual=All&locale=zh_CN&pageIndex=0&position=All&qualified=false&season=2021&seasonType=2&split=All+Team&statType=points&team=All&total=perGame'
  7 #
  8 def getHTMLText(url,timeout=30):
  9     try:
 10         r=requests.get(url,timeout=30) # 
 11         r.raise_for_status()
 12         r.encoding=r.apparent_encoding
 13         return r.text
 14     except:
 15         return'產生異常'
 16 
 17 #html.parser表示用BeautifulSoup庫解析網頁
 18 html=getHTMLText(url)
 19 soup=BeautifulSoup(html,'html.parser')
 20 print(soup.prettify())
 21 
 22 #創建空表
 23 pointsPg_list=[]
 24 assistsPg_list=[]
 25 rebsPg_list=[]
 26 name_list=[]
 27 data1=[]
 28 tppct=[]
 29 ftpct=[]
 30 fgpct=[]
 31 stealsPg_list=[]
 32 blocksPg_list=[]
 33 offRebsPg_list=[]
 34 defRebsPg_list=[]
 35 rank=[]
 36 html=getHTMLText(url)
 37 data=json.loads(html)
 38 a=data['payload']['players']
 39 data1.append(name_list)
 40 data1.append(assistsPg_list)
 41 b=1
 42 for i in a:   
 43     rank.append(b)
 44     name_list.append(i['playerProfile']['displayName'])
 45     pointsPg_list.append(i['statAverage'][ 'pointsPg'])
 46     rebsPg_list.append(i['statAverage'][ 'rebsPg'])
 47     assistsPg_list.append(i['statAverage'][ 'assistsPg'])
 48     stealsPg_list.append(i['statAverage'][ 'stealsPg'])
 49     blocksPg_list.append(i['statAverage'][ 'blocksPg'])
 50     offRebsPg_list.append(i['statAverage'][ 'offRebsPg'])
 51     defRebsPg_list.append(i['statAverage'][ 'defRebsPg'])
 52     tppct.append(i['statAverage']['tppct'])
 53     ftpct.append(i['statAverage']['ftpct'])
 54     fgpct.append(i['statAverage']['fgpct'])
 55     b=b+1
 56 list_1=['排名']
 57 
 58 #導出球員的各項數據
 59 import pandas as pd
 60 df=pd.DataFrame(columns=list_1)
 61 df['排名']=rank
 62 df['NAME']=name_list
 63 df['場均得分']=pointsPg_list
 64 df['場均籃板']=rebsPg_list
 65 df['場均助攻']=assistsPg_list
 66 df['投籃命中率']=fgpct
 67 df['三分命中率']=tppct
 68 df['罰球命中率']=ftpct
 69 df['進攻效率']=offRebsPg_list
 70 df['防守效率']=defRebsPg_list
 71 df['場均搶斷']=stealsPg_list
 72 df['場均蓋帽']=blocksPg_list
 73 df
 74 
 75 #將dataframe寫入csv
 76 df.to_csv('D:/Python/NBA數據.csv',index=False)
 77 df.to_csv('D:/Python/NBA.csv',index=False)
 78 
 79 #檢查並顯示重復值
 80 print(df.duplicated())
 81 
 82  #刪除重復值
 83 df = df.drop_duplicates()
 84 df.head()
 85 
 86 #異常值處理
 87 df.describe()
 88 
 89 #檢查是否有空值
 90 print(df['排名'].isnull().value_counts())
 91 
 92 #查看統計信息
 93 print(df.describe())
 94 df
 95 
 96 #求取回歸系數
 97 from sklearn.linear_model import LinearRegression
 98 X=df.drop('NAME',axis=1)
 99 predict_model=LinearRegression()
100 predict_model.fit(X,df['排名'])
101 print('回歸系數為:',predict_model.coef_)
102 
103 #繪制回歸圖
104 import seaborn as sns
105 import matplotlib.pyplot as plt
106 plt.rcParams['font.sans-serif']=['SimHei']#用來正常顯示中文標簽
107 X=df.drop('NAME',axis=1)
108 sns.regplot(df['排名'],df['進攻效率'])
109 sns.regplot(df['排名'],df['防守效率'])
110 plt.title('排名與進攻、防守效率圖')
111 
112 #繪制柱狀圖
113 import pandas as pd
114 import numpy as np
115 import matplotlib.pyplot as plt
116 plt.rcParams['font.sans-serif']=['SimHei']
117 plt.bar(df.排名, df.投籃命中率, color='b')
118 plt.xlabel("排名")
119 plt.ylabel("投籃命中率")
120 plt.title('排名與投籃命中率柱狀圖')
121 plt.show()
122 
123 #繪制散點圖
124 import pandas as pd
125 import numpy as np
126 import matplotlib.pyplot as plt
127 plt.rcParams['font.sans-serif']=['SimHei']
128 plt.rcParams['axes.unicode_minus'] = False   # 用來正常顯示負號
129 size=30
130 plt.scatter(df.排名, df.場均得分,size, color='b',alpha=0.6,marker='o')
131 plt.xlabel("排名")
132 plt.ylabel("場均得分")
133 plt.title('排名與場均得分柱狀圖')
134 plt.show()
135 
136 #罰球命中率與排名
137 import pandas as pd
138 import numpy as np
139 import matplotlib.pyplot as plt
140 plt.rcParams['font.sans-serif']=['SimHei']
141 plt.rcParams['axes.unicode_minus'] = False   # 用來正常顯示負號
142 plt.stackplot(df.排名, df.罰球命中率, color=['b',])
143 plt.xlabel("排名")
144 plt.ylabel("罰球命中率")
145 plt.title('排名與罰球命中率堆疊圖')
146 plt.show()
147 
148 #繪制折線圖
149 import pandas as pd
150 import numpy as np
151 import matplotlib.pyplot as plt
152 plt.rcParams['font.sans-serif']=['SimHei']
153 plt.rcParams['axes.unicode_minus'] = False
154 plt.plot(df.排名, df.三分命中率, color='b')
155 plt.xlabel("排名")
156 plt.ylabel("三分命中率")
157 plt.title('排名與三分命中率折線圖')
158 plt.show()
159 
160 #繪制擬合曲線
161 import matplotlib.pyplot as plt
162 import matplotlib
163 import numpy as np
164 import scipy.optimize as opt
165 import csv
166 x0=df['進攻效率']
167 y0=df['場均得分']
168 def func(x,c):
169     k,a=c
170     return k*x+a
171 def errfc(c,x,y):
172     return y-func(x,c)
173 c0=(100,20)
174 #調用擬合曲線
175 print(opt.leastsq(errfc,c0,args=(x0,y0)))
176 #s設置畫布
177 chinese=matplotlib.font_manager.FontProperties(fname='C:\Windows\Fonts\simsun.ttc')  
178 
179 plt.plot(x0,y0,"o",label=u"進攻效率")
180 
181 plt.plot(x0,func(x0,opt.leastsq(errfc,c0,args=(x0,y0))[0]),label=u"場均得分")
182 plt.title('進攻效率與場均得分擬合曲線圖')
183 plt.legend(loc=3,prop=chinese)
184 
185 plt.show()
186 
187 #繪制擬合曲線
188 import matplotlib.pyplot as plt
189 import matplotlib
190 import numpy as np
191 import scipy.optimize as opt
192 import csv
193 x0=df['防守效率']
194 y0=df['場均搶斷']
195 #
196 def func(x,c):
197     k,a=c
198     return k*x+a
199 def errfc(c,x,y):
200     return y-func(x,c)
201 c0=(100,20)
202 #調用擬合曲線
203 print(opt.leastsq(errfc,c0,args=(x0,y0)))
204 #s設置畫布
205 chinese=matplotlib.font_manager.FontProperties(fname='C:\Windows\Fonts\simsun.ttc')  
206 
207 plt.plot(x0,y0,"o",label=u"防守效率")
208 
209 plt.plot(x0,func(x0,opt.leastsq(errfc,c0,args=(x0,y0))[0]),label=u"場均搶斷")
210 plt.title('防守效率與場均搶斷擬合曲線圖')
211 plt.legend(loc=3,prop=chinese)
212 
213 plt.show()
214 
215 #數據持久化
216 df = pd.DataFrame(df,columns=['排名','NAME','場均得分','場均籃板','場均助攻','投籃命中率','罰球命中率','三分命中率','進攻效率','防守效率','場均搶斷','場均蓋帽'])
217 df.to_csv('NBA.csv',encoding = 'gbk') #保存文件,數據持久化

 

五、總結

1.經過對主題數據的分析與可視化,可以得到哪些結論?是否達到預期的目標?

通過一系列的數據分析及可視化可以發現,在爬取的這些球員之中,根據場均得分來進行的排名,事實上並不是能那么可靠地分析一個球員的好與壞,在場上不僅僅只有得分,還有其余的各項數據,投籃的命中率以及防守、進攻效率和對球隊的1幫助很大程度上並不是根據場均得分來體現,得分高命中率低,可能會導致球隊落后和失分。經過一系列數據對比我們可以的到此結論,達到了預期的目標。

2.在完成此設計過程中,得到哪些收獲?以及要改進的建議?

在完成設計的過程中,由於選題以及對爬取知識的欠缺耗費了大量的時間,期間瀏覽、了解、和學習了許多老師推薦的優秀作品,以及CSDN,博客園里的許多博主發布的很好的作品,讓我得到也學到了很多的新的知識,學到了很多不同的完善和解決同一個問題的方法,但是還沒有完全掌握並使用使之成為自己的東西,還需要在課后進行更仔細的研究。在完成設計的過程中,需要感謝一些掌握知識比較透徹的同學對我出現的問題的指正。在繪制分析圖時課本里的例題分析講解的也比較透徹,當然這些知識在課上也都很清楚地進行過講解,在課后作業中也進行了多次練習。在設計中,存在很多的不足之處,但是,通過這次設計能讓我更好地警醒自己的Python水平和理解的有限。同樣,這些不足會給我更大的動力去探索Python。總而言之,這次的設計很大程度,很大意義上對我起到了巨大的幫助和督促。課下的空余時間依然要不斷努力學習新的知識完善自己。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM