当前位置: 移动技术网 > IT编程>脚本编程>Python > Python爬虫项目之NBA球员可视化分析

Python爬虫项目之NBA球员可视化分析

2020年07月26日  | 移动技术网IT编程  | 我要评论

Python爬虫学习之NBA球员可视化分析

前言

最近刚上完Python选修课,一直挺喜欢Python的,觉得Python的简洁优美的代码像是在写诗一样让人看了赏心悦目,其次就是他强大的第三方库是其他语言所不能媲美的.有很多你需要用的功能,其实不需要学习他的底层架构,大多数情况下只用知道他的api接口就足够了.最后就是Python的爬取数据,科学计算的功能与最近很火的AI接轨,符合时代潮流

这次项目是来源于学校在假期的一个实训项目,由于自己是一名资深篮球爱好者,所以就选了这个项目.

选取目标网站

我选取的是 NBA中国官网,最权威的数据

对网站数据的理解

我们开始学习的是对html静态数据的爬取,可是大部分网站都是通过ajax,或者其他技术动态获取技术的,所以要对网站中的动态获取的部分进寻找

  • 打开开发者模式,在network的XHR中寻找动态获取的环节在其中寻找你想要获取数据的部分

在这里插入图片描述

数据爬取

数据爬取的流程

def main():     #主程序
    print("开始爬取.....")
    year=2010  #起始年份
    baseurl='https://china.nba.com/static/data/league/playerstats_All_All_All_0_All_false_2018_2_All_Team_points_All_perGame.json'
    #获得数据
    NBAPlayerdatadict=getdata(baseurl,year)
    #所需信息的抬头列表
    cols_index2 = ['displayName',"code", 'position', 'name',"code",'games','points', 'pointsPg', 'rebsPg', 'assistsPg''minsPg', 'fgpct', 'tppct', 'ftpct', 'blocksPg', 'foulsPg', 'height', 'weight'
                   ]
    cols_index1 = ['playerProfile','playerProfile', 'playerProfile', 'teamProfile',
                   'teamProfile',  'statAverage',
                   'statTotal', 'statAverage', 'statAverage', 'statAverage',
                   'statAverage', 'statAverage', 'statAverage', 'statAverage',
                   'statAverage', 'statAverage', 'playerProfile', 'playerProfile'
                   ]
    #保存数据
    savepath='.//'+str(year)+'年-2020年NBA球员数据排行TOP50.xls'
    savedata(NBAPlayerdatadict,savepath,year,cols_index1,cols_index2)
    #数据库位置
    dbpath='.//NBA球员数据库.db'
    #将数据保存到数据库
    saveDB(NBAPlayerdatadict,dbpath,year,cols_index1,cols_index2)
    print('成功爬取并保存数据!')

开始数据爬取,首先第一步你要将自己伪装成一个浏览器,所以在你请求获得数据的时候就要把自己的身份证(user-agent)写成浏览器的在这里插入图片描述

这里利用python的内置包urllib.request&error来模拟向浏览器发出请求,废话不多说上代码

def askUrl(url):      #获得请求得到一个html(字符串的形式)
    headers={     #伪装身份信息
        'User-Agent': 'Mozilla / 5.0(Windows NT 10.0;Win64;x64) AppleWebKit / 537.36(KHTML, likeGecko) Chrome / 80.03987.122Safari / 537.36'
    }
    request = urllib.request.Request(url,headers=headers)
    html=''
    try:
        response=urllib.request.urlopen(request) #提交
        html=response.read().decode('UTF-8')
        print("成功爬取到html!")
    except urllib.error.URLError as e:
        if hasattr(e, "code"):
            print(e.code)
        if hasattr(e, "reason"):
            print(e.reason)
        if isinstance(e.reason, socket.timeout):
            print('time out!')
    return html

数据解析

  • 由于获取到的数据(html)是php格式需要对文件进行正则表达式处理之后获得json数据格式

  • 利用json包对数据进行json解析,获得字典数据NBAPlayerdatadict

  • 利用列表对数据进行查找,获得我们想要的数据

def getdata(baseurl,year):    #爬取网页获得需要的数据
    Playerdatadict={}
    for i in range(year,2020):
        #创建模式匹配更换url获取不同年份的data
        pattern_date = re.compile(r'(_\d*?_\d)', re.S)
        newbaseurl = re.sub(pattern_date, '_'+str(i)+'_2', baseurl)
        html=askUrl(newbaseurl)
        # 将html中的文件进行json解析得到Playerdata字典
        Playerdata=json.loads(html)
        # 将Playerdata放大字典中并带上年份
        Playerdatadict.setdefault(str(i)+"年", {}).update(Playerdata)
        time.sleep(0.05)  # 设置爬虫间隔
    print('成功获取数据!')
    return Playerdatadict

数据保存

我们需要将数据保存到excel文件,利用xlwt库创建多个sheet工作表,将不同年份的数据保存在里面

def savedata(Playerdatadict,savepath,year,cols_index1,cols_index2):    #保存数据到Excel
    cols=['排名','球员','球员链接','位置','球队','球队链接',
          '出场数','赛季得分','场均得分','场均篮板',
          '场均助攻','分钟','命中率','三分命中率(%)',
          '罚球命中率','场均盖帽','场均失误','身高(m)','体重']
    workbook = xlwt.Workbook(encoding='UTF-8')  # 创建workbook
    for i in range(year, 2020):
        worksheet = workbook.add_sheet(str(i) + '年')  # 创建工作表
        for j in range(len(cols)):
            worksheet.write(0,j,cols[j])
        for k in range(len(Playerdatadict[str(i) + '年']['payload']['players'])):
            worksheet.write(k + 1, 0, k + 1)
            for n in range(len(cols_index1)):
                p_link = r'https://china.nba.com/players/#!/'
                t_link = r'https://china.nba.com/'
                # 从Playerdatadict将有效信息取出来
                Playerdatadict_info = Playerdatadict[str(i) + "年"]['payload']['players'][k][cols_index1[n]][
                    cols_index2[n]]
                if n != 1 and n != 4:
                    worksheet.write(k + 1, n + 1, Playerdatadict_info)
                elif n == 1:  # 球员链接+str(link)
                    worksheet.write(k + 1, n + 1, p_link + Playerdatadict_info)
                else:
                    worksheet.write(k + 1, n + 1, t_link + Playerdatadict_info)
    workbook.save(savepath)
    print('保存数据成功!')

将数据保存到数据库中,这里呢我用的是sqlite,一个轻量级嵌入在pycharm的数据库,比较简单,数据库的原理其实都一样,换其他数据库也是大同小异

首先初始化数据库

def initDB(tablename,dbpath):
    sql = '''
         create table ''' + str(tablename) + '''(
         ranking  integer primary key autoincrement,
         name    text,
         name_link text,
         position text,
         teamname text,
         team_link text,
         games   integer ,
         points  integer ,
         averpoints integer ,
         averrebound integer,
         averassist  integer ,
         minutes    integer ,
         fgpct      integer,
         tppct      integer,
         ftpct     integer ,
         averblocks integer ,
         averfouls  integer,
         height  integer,
         weight  text
         );
        '''
    con = sqlite3.connect(dbpath)  # 连接数据库
    c = con.cursor()  # 创建游标
    c.execute(sql)
    con.commit()
    c.close()
    con.close()
    print('表' + str(tablename) + "创建成功!")

把数据放到数据库中

def saveDB(Playerdatadict,dbpath,year,cols_index1,cols_index2):      #保存数据到数据库
    for i in range(year, 2020):
        #表的名称
        tablename="球员数据"+str(i)+'年'
        #初始化数据库
        initDB(tablename,dbpath)
        con=sqlite3.connect(dbpath)
        c=con.cursor()
        #Playerdatadict_info为从Playerdatadict字典里面提取到的有用信息
        Playerdatadict_info = Playerdatadict[str(i) + "年"]['payload']['players']
        for j in range(len(Playerdatadict_info)):   #球员信息个数len(Playerdatadict_info)
            data_need = []  # 每一行所需信息
            for k in range(len(cols_index1)):
                # 从Playerdatadict将有效信息取出来
                info = Playerdatadict_info[j][cols_index1[k]][cols_index2[k]]
                p_link = r'https://china.nba.com/players/#!/'
                t_link = r'https://china.nba.com/'
                if k!= 1 and k!= 4:
                    data_need.append(str(info))
                elif k==1:
                    data_need.append(p_link+str(info))
                else:
                    data_need.append(t_link + str(info))
            for index in range(len(data_need)):
                data_need[index] = '"' + data_need[index] + '"'
            sql = '''
                        insert into '''+str(tablename)+'''(
                        name,name_link,position,teamname,team_link,games,points,averpoints,averrebound,averassist,minutes,fgpct,tppct,ftpct,averblocks,averfouls,height,weight)
                        values (%s)'''%(",".join(data_need))
            c.execute(sql)
            con.commit()
        c.close()
        con.close()
    print('数据成功保存到数据库!')

数据爬取工作完毕!

利用flask框架进行网站的搭建

这里python web推荐使用flask框架flask官方中文文档

Flask是一个使用 Python 编写的轻量级 Web 应用框架。其 WSGI 工具箱采用 Werkzeug ,模板引擎则使用 Jinja2 。Flask使用 BSD 授权

Flask 很轻,花很少的成本就能够开发一个简单的网站。非常适合初学者学习。Flask 框架学会以后,可以考虑学习插件的使用。 如果你后续要用到更多的功能他还有各种各样的拓展包

这个我只用了flask的三个功能

from flask import Flask,render_template,request
import sqlite3,jieba
app = Flask(__name__)
@app.route('/')  #地址路由
def welcome():
    return  render_template('')
@app.route('/index')
def index():
    return welcome()
@app.route('/top50')
def top50():
    datalist = []
    con = sqlite3.connect("NBA球员数据库.db")
    c = con.cursor()
    #设置当前页数
    page=int(request.args.get('page',1))
    year=int(page)+2009
    sql= '''
    select * from 球员数据'''+str(year)+'''年
    '''
    data=c.execute(sql)
    for item in data:
        datalist.append(item)
    c.close()
    con.close()
    # 设置总页码数
    pagemax = 10
    return render_template('top50.html',datalist=datalist,page=page,pagemax=pagemax)
@app.route('/cloud')
def cloud():
    return render_template('cloud.html')
@app.route('/chart')
def chart():
    datalist = []
    years=[]  #年份
    xx=[]#x坐标数据
    #存放球队的名称的列表
    team=[['76人'], ['公牛'], ['凯尔特人'], ['勇士'], ['国王'], ['太阳'], ['奇才'], ['小牛'], ['尼克斯'], ['开拓者'], ['快船'], ['掘金'], ['森林狼'], ['步行者'], ['活塞'], ['湖人'], ['火箭'], ['灰熊'], ['热火'], ['爵士'], ['猛龙'], ['篮网'], ['老鹰'], ['雄鹿'], ['雷霆'], ['马刺'], ['骑士'], ['魔术'], ['鹈鹕'], ['黄蜂']]
    #存放球队名称的字符串
    # 存放字符的字符串
    text = ''
    con = sqlite3.connect("NBA球员数据库.db")
    c = con.cursor()
    # 设置当前页数
    page = 1
    year = int(page) + 2009
    for i in range(year, 2020):
        data_peryear = []
        years.append(i)
        sql = '''
                    select * from 球员数据''' + str(i) + '''年
                    '''
        data = c.execute(sql)
        for item in data:
            data_peryear.append(item)
            #将球队名称练成字符串
            text += item[4]
        datalist.append(data_peryear)
    for index in range(10):
        xx.append(str(index+2010)+str(datalist[index][0][1]))
    c.close()
    con.close()
    #利用字符串统计球队名称出现的次数
    for i in range(len(team)):
        number=text.count(team[i][0])
        team[i].append(str(number))
    return render_template('chart.html',datalist=datalist,years=years,xx=xx,team=team)
@app.route('/team')
def team():
    return render_template('team.html')

if __name__ == '__main__':
    app.run(debug=True)

wordcloud库生成词云

利用wordcloud库和jieba库对获取到的teamname和playername进行词云统计生成词云,得出出现次数最多的球员和球队


```python
import jieba
from matplotlib import pyplot as plt
import matplotlib.colors as colors
from wordcloud import WordCloud
from PIL import Image          #图片处理
import numpy as np
import sqlite3
import random
def random_color_func(word=None, font_size=None, position=None,  orientation=None, font_path=None, random_state=None):
        h  = random.randint(150,250)
        s = int(100.0 * 255.0 / 255.0)
        l = int(100.0 * float(random.randint(60, 120)) / 255.0)
        return "hsl({}, {}%, {}%)".format(h, s, l)
def playername():
    con = sqlite3.connect("NBA球员数据库.db")
    c = con.cursor()
    # 起始年份
    year = 2010
    # 存放字符的字符串
    text = ''
    for i in range(year, 2020):
        sql = '''
          select name from 球员数据''' + str(i) + '''年
        '''
        data = c.execute(sql)
        for item in data:
            text += item[0]
    cut = jieba.cut(text)
    string = ",".join(cut)
    print(string)
    c.close()
    con.close()
    img = Image.open(r'./static/assets/img/NBA.png')  # 打开图片
    img_array = np.array(img)  # 将图片转化为数组
    wc = WordCloud(
        background_color='white',
        mask=img_array,
        font_path="msyh.ttc",
        color_func=random_color_func
    )
    wc.generate_from_text(string)

    # 绘制图片
    fig = plt.figure(1)
    plt.imshow(wc)
    plt.axis('off')
    # plt.show()
    plt.savefig(r'./static/assets/img/namecloud.png', dpi=1000)
def teamname():
    con = sqlite3.connect("NBA球员数据库.db")
    c = con.cursor()
    # 起始年份
    year = 2010
    # 存放字符的字符串
    text = ''
    for i in range(year, 2020):
        sql = '''
              select teamname from 球员数据''' + str(i) + '''年
            '''
        data = c.execute(sql)
        for item in data:
            text += item[0]
    cut = jieba.cut(text)
    string = ",".join(cut)
    print(string)
    c.close()
    con.close()
    img = Image.open(r'./static/assets/img/乔1.jpg')  # 打开图片
    img_array = np.array(img)  # 将图片转化为数组
    wc = WordCloud(
        background_color='white',
        mask=img_array,
        font_path="msyh.ttc",
        color_func=random_color_func
    )
    wc.generate_from_text(string)

    # 绘制图片
    fig = plt.figure(1)
    plt.imshow(wc)
    plt.axis('off')
    # plt.show()
    plt.savefig(r'./static/assets/img/teamcloud.png', dpi=900)

``

利用echarts进行可视化分析

ECharts,一个使用 JavaScript 实现的开源可视化库,可以流畅的运行在 PC 和移动设备上,兼容当前绝大部分浏览器(IE8/9/10/11,Chrome,Firefox,Safari等),底层依赖矢量图形库 ZRender,提供直观,交互丰富,可高度个性化定制的数据可视化图表。 echarts官方文档

利用后端的数据制作饼状图和柱状图将数据可视化

网站成果

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

本文地址:https://blog.csdn.net/weixin_43631377/article/details/107577121

如对本文有疑问, 点击进行留言回复!!

相关文章:

验证码:
移动技术网