赞
踩
最近刚上完Python选修课,一直挺喜欢Python的,觉得Python的简洁优美的代码像是在写诗一样让人看了赏心悦目,其次就是他强大的第三方库是其他语言所不能媲美的.有很多你需要用的功能,其实不需要学习他的底层架构,大多数情况下只用知道他的api接口就足够了.最后就是Python的爬取数据,科学计算的功能与最近很火的AI接轨,符合时代潮流
这次项目是来源于学校在假期的一个实训项目,由于自己是一名资深篮球爱好者,所以就选了这个项目.
我选取的是 NBA中国官网,最权威的数据
我们开始学习的是对html静态数据的爬取,可是大部分网站都是通过ajax,或者其他技术动态获取技术的,所以要对网站中的动态获取的部分进寻找
数据爬取的流程
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('数据成功保存到数据库!')
数据爬取工作完毕!
这里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('index.html') @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库和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,一个使用 JavaScript 实现的开源可视化库,可以流畅的运行在 PC 和移动设备上,兼容当前绝大部分浏览器(IE8/9/10/11,Chrome,Firefox,Safari等),底层依赖矢量图形库 ZRender,提供直观,交互丰富,可高度个性化定制的数据可视化图表。 echarts官方文档
利用后端的数据制作饼状图和柱状图将数据可视化
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。