隨機森林預測NBA籃球賽(一)——數據爬取


  小編也是最近在學習數據挖掘,看到了第三章用決策樹預測獲勝的球隊。然而,NBA官網早就改版了,Export不能全部下載一年的數據記錄,只能按月,而且我也下載不了。想了想,就只能爬取了。話不多說。

  小編最開始用的Xpath,感覺路徑有點麻煩,而且速度好像也沒有BeautifulSoup快,所以小編就選用了pyquery和BeautifulSoup兩個方法實現爬取數據。

  首先,先查看網站,看到每月的數據,對應的url與月份有關,因此定義函數用於獲取每月的數據,輸入變量為月份。

  下面的函數為pyquery的方法。

import requests
from pyquery import PyQuery as pq
from bs4 import BeautifulSoup
import csv

headers = {
    'user-agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.130 Safari/537.36'
}
def get_data_pyquery(month):
    # 構造請求url
    url = 'https://www.basketball-reference.com/leagues/NBA_2014_games-{}.html'.format(month)
    result = requests.get(url, headers=headers).text
    doc = pq(result)
    # 用於存儲表頭
    header = []
    # 解析html
    for thead in doc.find('thead tr th').items():
        text = thead.text()
        # 忽略空白符
        # print(text)
        if(len(text)>2):
            header.append(text)
    # 存儲數據
    # print(header)
    data_all = []
    for tr in doc('tbody tr').items():
                data = []
                try:
                    data.append(tr.find('th').text())
                    for i in ([t.text() for t in tr('td').items()]):
              # 用於清除‘OT’不想關的數據
if i and not('OT' in i): data.append(i) # print(data) data_all.append(data) # print(data_all) except: print('有點錯誤,已忽略') return header,data_all

  下面的為BeautifulSoup:

def get_data_bs4(month):
    url = 'https://www.basketball-reference.com/leagues/NBA_2014_games-{}.html'.format(month)
    result = requests.get(url).text
    soup = BeautifulSoup(result,"lxml")
    data_all = []
    for i in range(len(soup.tbody.find_all("tr"))):
        data = []
        # 添加時間
        data.append(soup.tbody.find_all("tr")[i].find_all("th")[0].getText())
        for j in range(len(soup.find_all("tr")[i].find_all("td"))):
            data.append(soup.find_all("tr")[i].find_all("td")[j].getText())
        # 添加沒次的數據
        data_all.append(data)
    # print(data_all)
    return data_all

  這種方法有待完善,爬取的數據不是很全,有紕漏。(小編懶,不改了)

小編着重 用pyquery的方法。

接下來上主函數:

def get_csv():
    i = 0
    a = 0
    months = ['october','november','december','january','february','march','april','may','june']
    with open('NBA13_14.csv', 'w')as f:
        writer = csv.writer(f)
        for month in months:
            header,data = get_data_pyquery(month)
            if i == 0:
                writer.writerow(header)
                i += 1
            writer.writerows(data)
            a += 1
            print("第{}個月份 寫入完畢".format(a))

    print("NBA 2012-2014 共{}月份的數據寫入完畢!!".format(str(i)))

  輸出結果:

 

  上述代碼得到csv格式,注意:

  在4月份的數據中,有一行不符合規則: 

  小編用的try,except,直接忽略錯誤,但同時Playoffs也寫入到了文件中。

   Playoffs,在得到的csv表格中,刪除即可。

 

------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

  下面獲取上一個賽季的比賽記錄,這里的代碼需要重新寫:

  一開始,小編還是按照網址:view-source:https://www.basketball-reference.com/leagues/NBA_2013_standings.html

  右擊檢查,查找對應的源代碼,如果直接查看網頁源代碼的化,確實可以看到對應的代碼。於是小編就按照看到的寫,最后發現數據對不上。

  小編查看對應的源代碼,發現:

  小編發現,想爬取的數據都在 注釋里面。那想必是網頁在加載的過程中有JS的動態渲染。這是小編想用selenium或這splash訪問,結果都是TimeOuts,出現延遲。

這是,Embed this Table。彈出來了JS代碼的一個鏈接。發現里面的網址對應代碼有想要的數據。與原來的對比了一下,HTML結構一致,那么就可以進行爬取了。

  下面直接上代碼,小編用的Beautifulsoup,當然pyquery也可以,感興趣的可以自己試一下。

from bs4 import BeautifulSoup
import requests
import csv

headers = {
    'user-agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.130 Safari/537.36'
}

def get_data_bs4(url):
    html = requests.get(url).text
    soup = BeautifulSoup(html, 'lxml')
    # 要插入的數據
    data_all = []
    header = []
    tr = soup.find_all(name='tr')[1]
    for th in tr.find_all(name='th'):
        header.append(th.string)
    # print(header)
    data_all.append(header)
    # 下面來獲取數據
    tbody = soup.find(name='tbody')
    for tr in tbody.find_all(name='tr'):
        data = []
        data.append(tr.th.string)
        for td in tr.find_all(name='td'):
            data.append(td.string)
        data_all.append(data)
    return data_all


def get_csv(data_all):
    with open('NBA12-13.csv', 'w') as f:
        writer = csv.writer(f)
        for i, data in enumerate(data_all):
            writer.writerow(data)
            print("第 {} 名數據下載完畢".format(i + 1))
        print("文件下載完畢")




if __name__ == '__main__':
    url = 'https://widgets.sports-reference.com/wg.fcgi?css=1&site=bbr&url=%2Fleagues%2FNBA_2013_standings.html&div=div_expanded_standings'
    data = get_data_bs4(url)
    get_csv(data)

 

  完畢!!!!!

 


免責聲明!

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



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