NBA Fantasy的球員推薦系統(Python)

WEED
11 min readJan 6, 2020

1.前言&動機:

約莫在去年年底,在逛台灣NBA官方時看到了NBA Fantasy活動,這是一個透過選球員並將其數據轉換成分數的遊戲,而每週積分第一名的人能得到一件球衣。

忽然想起大學時期投入運彩的日子,體內的賭癮又蠢蠢欲動。比起大學時期的感性投注法,現在的我已經學會數據的重要性了!(用多少午餐錢換來的QAQ),於是馬上著手寫了球員的推薦系統,並且設定排程讓電腦每晚定時透過LINE發給我名單,以下是我的程式內容。

圖為台灣NBA FANTASY官方

2.抓取數據

既然要分析球員,那數據是最重要的吧,我們所需要的數據主要有以下三種:

a.每日球員數據

b.傷兵名單&觀察名單

c.Fantasy遊戲中的球員數據(包含位置,能力值等等)

在處理資料前,下列是我有import的套件,供參考:

每日數據

首先就從每日球員數據開始吧!先附上程式碼:

首先我們到basketball-reference找到每日球員數據,觀察網址可知每日的數據組成由網址內的mon/day/year來控制,因此定義一個參數是(mon,day,year)的函式nbastat,如此一來就能透過改變參數得到不同日期的球員數據。

這時我們回到fantasy看官方的計分規則:

照著計算規則,我們新增一道column['score’]

data['score'] = data['PTS']*1 + data['TRB']*1.2 + data['AST']*1.5 + data['STL']*3 + data['BLK']*3 - data['TOV']*1

如此一來,我們就能得到所需的每日球員數據了!

以1/2(美國時間)賽程的數據為例

平均得分&每日前十名次數

而單一一場數據並不足以代表一個球員的好壞,我們需要的是多場比賽累積下來的平均數據,這會更精準地幫助我們評價一個球員。

因此這時我們需要另一個函式:

從top_players這個函式中,我們給定一個日期,而這個函式就會幫我們找出從開幕戰到我們指定的這個日期中所有比賽的數據(此外,也能因應近況只取近一個月的資料),並從中可以得到兩個重要的資訊:

  1. AVG
  2. top_10_times

AVG能告訴我們此球員的平均score是多少,而top_10_times可以告訴我們此球員從開幕戰到現在總共進過幾次每日積分前十名。

累積時間至1/2(美國時間)為例

有了這兩項數據,我們更能清楚地知道哪一個球員能夠為我們帶來更高的得分收益。

球員比對

而除了用AVG來比較球員外,我們也能從圖表來判斷哪些球員表現較為穩定,這時我們能用seaborn來畫圖。

如圖所示,若比對Ben Simmons(藍)和Giannis Antetokounmpo(橘)這兩個球員,可以明顯看出Antetokounmpo的表現比Simmons來得穩定且優秀。

傷兵名單&觀察名單

接下來,由於遊戲規則很清楚地說到

因此知道哪些球員在受傷&觀察名單中是很重要的事情,畢竟誰都不想選到零分仔,此時我們可以去CBSSPORTS這個網站,找到每日的NBA Injuries資訊,這裡就能得到最新的傷兵以及觀察名單。

知道在哪可以爬到資料後,就是開始寫程式的時間了!

如此一來,我們就能得到一個List,裡面裝著所有出現在NBA Injuries的球員,同時我也把裡面的球員分成三類:有預期回歸日期/Game Time Decision/OUT,除了GTD的球員是當天決定是否上場之外,另外兩種球員幾乎是確定不會上場,目前我是保險起見只要在injury list的球員我都篩掉,但各位可以自行決定要不要加上GTD球員。

Fantasy遊戲中的球員數據(包含位置,能力值等等)

我們再回到遊戲規則,可以看到選球員的方式與限制。

為了讓程式能夠符合規則做推薦,我們需要把每個球員的位置以及能力值輸入進去。

首先,我們得先知道要從哪裡能夠得到這些資料,最直覺的地方當然就是直接去Fantasy主頁找了哦哦哦!

果然是在主頁呢

這時我們會遇到第一個爬蟲的問題,這些資料需要登入後才會顯示,如果單純用爬蟲連頁面是得不到資料的,於是我們得靠selenium這個套件幫助我們做模擬登入。

這時我們就把明天所有對戰組合中的球員資訊都存進NBA_STAT裡面了。

加入球員的位置

首先我們先用前面的top_players函式整理出從開幕戰到今天的球員數據,並存入top_table中,再來就在top_table內新增’position’這個column就好。

新增前我們可以看到每個球員的位置都不盡相同,但基本上可以分成五種:G / F-G / F / F-C / C,有複合位置的球員可以勝任兩個位置。

將位置整理出來後我們還需要另一個套件fuzzywuzzy,此套件可以做模糊比對,將相似的兩個字串視為同一個字串,這動作主要是針對歐陸球員的名字,例如達拉斯新希望 Luka Dončić,在不同的網站上可能會直接打成Luka Doncic,這時python會把這兩個字串視為不同的字,但用fuzzywuzzy便能辨識出此兩字是高度符合,因此可以視為同一人。

加入球員的隊伍與能力值

與加入位置相同的邏輯,也加上球員的所屬球隊以及能力值吧!最後我們會得到tmr_set,裡面裝有明天會出場的球員以及該球員的資訊。

區分主客場球員

主客場對於球員表現來說也是至關重要的一部份,多數球員主場打得比較好,但也有些球員特別擅長打客場,因此我們把明日對戰組合的主客場分開計算,主場球員用主場數據(AVG),客場球員則是用客場數據(AVG),如此可以得到更準確的推薦。

加入球員的健康狀況

還記得前幾個步驟做的injury list嗎,現在可以派上用場了,在tmr_set加入這個List後,我們就能篩選出哪些球員不在傷兵&觀察名單中,大大降低選到零分仔的機會(雖然球隊很可能在賽前臨時決定上場球員就是了)。

以下是最終的DataFrame:

取自台灣時間1/6

3.推薦組合

終於,前置作業都做完後,我們可以開始做球員的推薦了,而我們的推薦邏輯很簡單,哪一組的AVG總和高就推哪一組,但在計算AVG之前我們還有幾個小步驟要做:

篩選與加權

透過加權,進過越多次每日top 10的球員就能得到越高的加權,程式也會偏向選擇這些球員,這情況也符合玩家選球員時會選明星球員的舉動,而篩掉平均AVG以下的球員以及能力值75以下的球員除了符合玩家的選人標準外,也能幫我們的程式跑得更快。

依照位置分組

將不同位置的球員區分為後衛/前鋒/中鋒群,在選球員時就只要從相對應的位置中選擇需要的球員就好,不需要全部掃過一遍,此舉也能大幅降低程式的運算壓力。

開始計算推薦組合

這時就是用窮舉法,把每個可能的組合都找出來,並且加上 "總能力值介於420~430之間" 以及 "每個球員都不重複" 這兩個條件,最後符合條件的隊伍組合就會儲存在team這個List裡面。

接下來只要把這些組合的總AVG加總起來,便可以由高分到低分做排列,我們只取前三高的組合當參考,結果如下:

台灣時間1/6預測的第一組
台灣時間1/6預測的第三組

4.透過LINE傳送結果

寫好程式後由於不是隨時都在家裡可以手動執行,因此設定電腦排程透過LINE傳送程式結果到手機上是很重要且方便的,而設定也不複雜,只要透過以下步驟便能輕鬆做到了。

LINE Notify

首先先到LINE Notify的頁面申請加入好友,如此一來便能透過Notify與其他服務連動,即時傳送訊息給自己。

IFTTT

剛剛在申請LINE Notify的時候就能在下面看到IFTTT了,IFTTT如其口號「if this then that」,即是在A服務發生某件事時,B服務就做出某個反應,透過此服務可以讓程式執行時觸發LINE傳送訊息。

申請完登入後按右上角人像並點選Create後進到此頁面,首先點選This的+號並搜尋webhooks。

點選connect後選擇服務。

接下來會要建立一個trigger,這是用來辨別服務的唯一名稱,所以要記得它,而命名規則則是不能用特殊符號或空白。

接下來要點選That的+號。

搜尋LINE,並進行設定,這時需要輸入LINE的帳號密碼,輸入完後點選send message的服務。

點選之後會進到這樣的頁面,第一欄可以決定要讓Notify發在哪一個群組,但前題是要把Notify先加到該群組,而第二欄則是傳送的訊息,我們只會用到Value1所以只留這個就好。

除了剛剛的trigger要記住之外,Webhook給的金鑰也是要記得的哦,如果忘記的話可以回到首頁依序點選Webhooks→Setting,找到下面的 URL資訊,在/use/後面那一串20幾碼的英數字就是金鑰了。

電腦排程

接下來先回到程式,定義一個寫入我們trigger和金鑰的函式後,就可以透過此函式傳送資料到我們的LINE上了。

而整個寫好的程式則可以透過排程來定時自動執行,首先先搜尋電腦內的 "工作排程器 ",打開後點選最右方的" 建立工作 ",而需要調整的地方有" 一般 "、" 觸發程序 "、" 動作 "這三個部分。

" 一般 " 這一欄主要是在名稱欄取名,以及下面安全性選項的設定。

" 觸發程序" 則是可以設定觸發的時間。

" 動作 "則是新增一個bat檔,電腦到排程時間時會執行這個bat檔的動作。

創立bat檔最簡單的方法是打開txt檔後儲存,並把附檔名改成bat就可以了,而我們需要的bat檔內容可以參考:

5.大功告成

經歷了千辛萬苦,我們終於做出自動推薦程式了,下圖是成果顯示在LINE上的樣子,第一欄是今日積分前十名的球員,接下來是三組明日預測。

最後,感謝各位看完,有任何問題也請多指教,並預祝大家得高分!

2020/1/14(台灣時間)預測程式排名衝上前五名啦!

--

--