用 Python 分析韋德職業生涯資料
2018 註定是不平凡的一年,這一年有太多我們熟知的大師離去。他們的離去代表著一個時代的終結,也代表這我們 90 後青春的落幕。我們這代 90 後是個男生都會看場 NBA 的比賽。
2013 那年我高二也是 NBA 球隊熱火隊最火爆的時期,詹偉連線無人可擋。
那年的總決賽,熱火大比分 2-3 落後馬刺,當時第六場的最後幾秒熱火的比分還是落後於馬刺,眼看就要輸掉了比賽。那時候我們還在上課,但為了看熱火這場生死大戰,我和幾個死黨一起逃課。當時我們都覺得熱火已經沒有希望了,都準備要回去,但就在比賽快要結束時雷阿倫投入高難度扳平三分,從而把比賽拖入加時,最終逆轉奪冠!我們幾個當場就大喊起來:熱火牛逼!
絕殺總是能讓人激動不已!在NBA歷史上,留下了不少的經典絕殺!我們的閃電俠韋德也是個中佼佼者,其中 2009 年對陣公牛一役完成搶斷三分絕殺就是一大例證,絕殺之後韋德跑到站臺上更是霸氣的喊到「This is my house」。
當年的熱火給我們的青春帶來了太多的回憶,雖然曾經的隊友,早已成為了彼此的對手。就像當年一起通宵的死黨,如今都已變成陌生人,都在為現實奔波。
而就在昨天 12 月 11 日美國當地時間 10 日晚,NBA 常規賽湖人主場迎戰熱火隊,這也是詹姆斯和韋德生涯最後一次常規賽對決。這場比賽就像多年以後老朋友再次相見,有太多不捨的回憶。賽後詹姆斯和韋德生互相交換了球衣,這個場景不知戳中多少球迷的心。
今天就帶大家用 Python 分析韋德職業生涯的資料,多年以後或許還可以拿出這篇文章給自己的孩子訴說這自己的青春。
資料獲取
資料的來源主要是爬 basketball-reference 網站上的資料。
網站地址:
https://www.basketball-reference.com/players/w/wadedw01.html
網站把韋德所有的生涯資料都展示出來,結構也很清晰我們只要用 requests + pyquery 解析就好。
最後我們把解析到的資料利用 pandas 儲存到 excel 中即可。
具體的爬蟲程式碼如下:
from pyquery import PyQuery as pq
from fake_useragent import UserAgent
import requests
import pandas as pd
def parse_html():
url = "https://www.basketball-reference.com/players/w/wadedw01.html"
ua = UserAgent()
headers = {"User-Agent": ua.random}
reponse = requests.get(url, headers=headers)
if reponse.status_code == 200:
html = reponse.text
extract_htm(html)
def extract_htm(html):
doc = pq(html)
Dwyane_Wade_data = []
data_items = doc.find("#div_per_game #per_game tbody tr").items()
for itme in data_items:
season = itme.find("th[data-stat='season'] a").text()
age = itme.find("td[data-stat='age']").text()
team = itme.find("td[data-stat='team_id'] a").text()
league = itme.find("td[data-stat='lg_id'] a").text()
position = itme.find("td[data-stat='pos']").text()
games = itme.find("td[data-stat='g']").text()
games_started = itme.find("td[data-stat='gs']").text()
minutes_played_per_game = itme.find("td[data-stat='mp_per_g']").text()
field_goals_per_game = itme.find("td[data-stat='mp_per_g']").text()
field_goals_attempts_per_game = itme.find("td[data-stat='fga_per_g']").text()
field_goal_percentage = itme.find("td[data-stat='fg_pct']").text()
point_3_field_goal_per_game = itme.find("td[data-stat='fg3_per_g']").text()
point_3_field_goal_percentage = itme.find("td[data-stat='fg3_pct']").text()
point_2_filed_goals_per_game = itme.find("td[data-stat='fg2_per_g']").text()
point_2_filed_goals_attempts_per_game = itme.find("td[data-stat='fg2a_per_g']").text()
fg2_pct = itme.find("td[data-stat='fg2_pct']").text()
efg_pct = itme.find("td[data-stat='efg_pct']").text()
ft_per_g = itme.find("td[data-stat='ft_per_g']").text()
fta_per_g = itme.find("td[data-stat='fta_per_g']").text()
ft_pct = itme.find("td[data-stat='ft_pct']").text()
orb_per_g = itme.find("td[data-stat='orb_per_g']").text()
drb_per_g = itme.find("td[data-stat='drb_per_g']").text()
trb_per_g = itme.find("td[data-stat='trb_per_g']").text()
ast_per_g = itme.find("td[data-stat='ast_per_g']").text()
stl_per_g = itme.find("td[data-stat='stl_per_g']").text()
blk_per_g = itme.find("td[data-stat='blk_per_g']").text()
tov_per_g = itme.find("td[data-stat='tov_per_g']").text()
pf_per_g = itme.find("td[data-stat='pf_per_g']").text()
pts_per_g = itme.find("td[data-stat='pts_per_g']").text()
item_data = {'season': season, "age": age, "team": team, "league": league, "position": position, "games": games,
"games_started": games_started, "minutes_played_per_game": minutes_played_per_game, "field_goals_per_game": field_goals_per_game,
"field_goals_attempts_per_game": field_goals_attempts_per_game, "field_goal_percentage": field_goal_percentage,
"point_3_field_goal_per_game": point_3_field_goal_per_game, "point_3_field_goal_percentage": point_3_field_goal_percentage,
"point_2_filed_goals_per_game": point_2_filed_goals_per_game, "point_2_filed_goals_attempts_per_game": point_2_filed_goals_attempts_per_game,
"fg2_pct": fg2_pct, "efg_pct": efg_pct, "ft_per_g": ft_per_g, "fta_per_g": fta_per_g, "ft_pct": ft_pct,
"orb_per_g": orb_per_g, "drb_per_g": drb_per_g, "trb_per_g": trb_per_g, "ast_per_g": ast_per_g, "stl_per_g": stl_per_g,
"blk_per_g": blk_per_g, "tov_per_g": tov_per_g, "pf_per_g": pf_per_g, "pts_per_g": pts_per_g}
print(item_data)
Dwyane_Wade_data.append(item_data)
data = pd.DataFrame(Dwyane_Wade_data)
data.to_csv("Dwyane_Wade_data.csv", encoding='utf_8_sig')
if __name__ == '__main__':
parse_html()
最後儲存的 excel 表如下:
出場次數和首發資料分析
首先我們對韋德生涯參加的場數和時間進行一個分析。
games:參與的比賽場數(都為82場)
games_start: 先發次數
age:年齡
minutes_played: 平均每場比賽進行的時間
韋德 22 歲就進入 NBA 打比賽,出道就打了 61 場比賽,首發 56 場,往後的幾年時間裡都是打球隊首發人員。一個賽季按 82 場來算,韋德在 2008 - 09 賽季恐怖的達到了 79 場比賽。
平均每場比賽時間都在 30 分鐘以上。
從這些資料可以看出韋德是隊伍中的主力軍,絕對的領袖。
投球命中率
韋德投球命中率平均在 0.47 。
2013-14 賽季達到職業生涯最大命中率:0.55。
由於篇幅的問題其他的資料就暫時不再繼續分析,感興趣的同學可獲取相應的原始碼進行分析,這裡給大家一個單詞對照表。
連結: https://pan.baidu.com/s/1PCQ-gEX-aaV5JvgDva_0lQ 提取碼: dx73
資料名 | 含義 |
---|---|
Rk -- Rank | 排名 |
G -- Games | 參與的比賽場數(都為82場) |
MP -- Minutes Played | 平均每場比賽進行的時間 |
FG--Field Goals | 投球命中次數 |
FGA--Field Goal Attempts | 投射次數 |
FG%--Field Goal Percentage | 投球命中次數 |
3P--3-Point Field Goals | 三分球命中次數 |
3PA--3-Point Field Goal Attempts | 三分球投射次數 |
3P%--3-Point Field Goal Percentage | 三分球命中率 |
2P--2-Point Field Goals | 二分球命中次數 |
2PA--2-point Field Goal Attempts | 二分球投射次數 |
2P%--2-Point Field Goal Percentage | 二分球命中率 |
FT--Free Throws | 罰球命中次數 |
FTA--Free Throw Attempts | 罰球投射次數 |
FT%--Free Throw Percentage | 罰球命中率 |
ORB--Offensive Rebounds | 進攻籃板球 |
DRB--Defensive Rebounds | 防守籃板球 |
TRB--Total Rebounds | 籃板球總數 |
AST--Assists | 輔助 |
STL--Steals | 偷球 |
BLK -- Blocks | 封阻 |
TOV -- Turnovers | 失誤 |
PF -- Personal Fouls | 個犯 |
PTS -- Points | 得分 |
在很多年後,當老詹和騷韋挺著日漸臃腫的肚子來到球場,看著場上的小詹和小腮幫在球場上盡情揮灑著天賦,一次次的空接暴扣,一次次的搶斷反擊,聽著場下一聲又一聲的吶喊,會不會忽然就溼潤了眼眶。
此文紀念我們逝去的青春。