虎扑数据爬取+球员能力分布雷达图

学了一阵子python后,心痒痒想爬个网站试试,但得找个自己感兴趣的啊,那必然是篮球了。想了想平时看篮球的也就腾讯和虎扑,细心的jrs可能会发现腾讯体育点进球员个人主页会有五角形的能力分布图,虎扑则是各类数据比较详尽,所以博主就想着是不是可以爬一爬虎扑,然后做个球员的能力分布图。

话不多说,先上张效果图

输入对应球员名字就可以获得相应球员的能力分布图了,话说最终效果还是不错的!

那具体是怎么实现的呢?

将我们的实现过程分为两步,第一,爬取虎扑网页上球员的个人信息,存入文件中;第二,读取文件,制作球员能力分布图

1. 虎扑球员个人数据爬取

  • 首先,打开虎扑网页[https://nba.hupu.com/stats/players/pts](这个我称之为页面一,后面都这样叫了)

    我们观察发现虎扑有个数据网页,有各个球员对应的部分信息,是部分信息,这个网页只有与球员得分有关的信息,球员的详尽信息要点击球员的名字进去,然后我们点击斯蒂芬-库里进去
    (这个我称之为页面二,后面都这样叫了))

    发现这里有库里的各类信息,而我们要提取的就是得分、助攻、抢断、篮板、盖帽、投篮命中率、三分命中率信息。
    看到这里,基本的想法就出现了,我们可以通过打开球员得分排行榜的那个网页(也就是页面一),然后一个一个点击球员的名字进入到球员个人主页(页面二)获取我们想要的信息。

  • 然后我们就要分析网页的源代码了
    使用浏览器的检查地位功能(页面一)

    发现球员的名字都存在‘td,left’里,所以我们只要定位这个标签,然后再模拟浏览器点击(click())进个人主页就好了(页面二)

    同样用浏览器的代码检查功能,定位到球员的个人数据都存储在span.b的元素里,所以到时我们获取球员个人信息时只要定位到这个标签提取其文本信息就行了

基本的思路就是这样,接下来直接贴代码了(代码后有详细的注释,包括我遇到的一些问题)整个爬取过程大概要十几二十分钟

# -*- coding: utf-8 -*-
"""
Created on Sun Oct 21 19:38:57 2018@author: ninewolfyan
@email: 821562236@qq.com
"""
#import string
from selenium import webdriver
import syseachplayerinfo=[]
playername=[]
score=[]
rebound=[]
block=[]
steal=[]
shootrate=[]
threerate=[]
assist=[]#提取一个球员的所有数据
def eachinfo(k):k=kfor i in range(0,50):try:#这个try,except是防止爬到最后一个球员还在循环,不加就会继续爬,而没了球员数据会报错driver.get("https://nba.hupu.com/stats/players/pts/"+str(k))#每循环一次,因为点击了新的页面,所以我们需要刷新到原来的页面,不然找不到原页面的信息,会报错pagerefresh=driver.find_element_by_css_selector('table.players_table')#这行其实不用写的,但这是一个好习惯,先定位到tr的上一个节点,这样在找tr时万一别的地方还有tr标签,就容易爬错信息了playerlist=pagerefresh.find_elements_by_tag_name('tr')eachplayername=playerlist[i+1].find_element_by_css_selector('td.left')#如果该位置的信息只有单个,则不能用elements,否则会报错,只能用elementplayername.append(eachplayername.get_attribute('textContent'))try: #因为球员个人的全部信息在个人主页里,所以用click点进去获取moreinfo=playerlist[i+1].find_element_by_css_selector('a')moreinfo.click()except:passpagestats=driver.find_element_by_css_selector('div.gamecenter_content')stats=pagestats.find_elements_by_css_selector('span.b')try: #这个try,except是因为泰森钱德勒的存在,虎扑关于它个人页面的那一栏数据没有,获取不了,只能跳过了score.append(stats[1].text) #关于得分助攻等信息就得看清对应的是第几个index了assist.append(stats[2].text)rebound.append(stats[3].text)steal.append(stats[8].text)block.append(stats[7].text)shootrate.append(stats[4].text)threerate.append(stats[5].text)except:pass   #异常处理,出现异常直接跳过except:passreturn playername,score,assist,rebound,steal,block,shootrate,threerate#主函数(遍历六页网页)
driver=webdriver.Chrome()
for i in range(1,7):driver.get("https://nba.hupu.com/stats/players/pts/"+str(i))eachinfo(i)#存入文件输出,(chr(12288)是用中文字符填充空格,对齐更整齐)
output=sys.stdout
outputfile=open("playerdata.txt",'w',encoding='utf-8')
sys.stdout=outputfile
outputMode= "{0:{8}^15}\t{1:^5}\t{2:^5}\t{3:^5}\t{4:^5}\t{5:^5}\t{6:^10}\t{7:^10}"
print(outputMode.format('球员名字', '得分', '助攻', '篮板','抢断','盖帽','投篮命中率','三分命中率',chr(12288)))#chr(12288)表示用中文字符填充
for i in range(0,283):print(outputMode.format(playername[i],score[i],assist[i],rebound[i],steal[i],block[i],shootrate[i],threerate[i],chr(12288)))
outputfile.close()
sys.stdout=output

有几个值得注意的点(部分也是我遇到的问题):

1.得分排行榜的网页一共六页,网址间有很好的关系
https://nba.hupu.com/stats/players/pts/1
https://nba.hupu.com/stats/players/pts/2
第二页和第一页只差一,所以可以用一个遍历循环分别定位到六页网页
2.善于运用try,except,只有自己不断的试才能发现这个东西真的好用,特别是在爬网页的时候,有些数据是空的,用个pass跳过就好了,不然就会一直卡在那
3.注意泰森-钱德勒,泰森-钱德勒,这个人被太阳买断了,然后点进他的主页没有数据,你不用try,except就会卡在那,而且因为球员的姓名我们是在球员得分榜(页面一)获取的,而个人信息是在球员个人主页(页面二)获取的,钱德勒相当于有姓名但没有个人信息,所以在爬钱德勒的时候,只有他的名字没有其他信息,但是爬下一个球员时,信息会向上替补,所有会出现信息混乱的情况,幸好钱德勒排在了倒数几位,所以只要打开生成txt手动调一下就好了,当然也可以用代码删掉钱德勒,不爬他,但我觉得太麻烦就没搞
4.得分、助攻、抢断等信息一定要对应,值得注意的是得分是span.b的第二条信息,第一条是‘数值’,藏在div.border里了

5.我用的是chrom,网上没有火狐浏览器的selenium,geckodriver对应版本,要自己一个一个试,很头疼的,谷歌浏览器及其对应的chromdriver可以很容易在网上找到

2.制作球员能力分布雷达图

制作球员能力雷达图重点不在于怎么画雷达图(雷达图参考的是霍兰德人格分析),而在于怎么分析处理数据

这一块就不具体分析步骤了,直接贴代码,提一下需要注意的点

Created on Sun Nov  4 19:11:12 2018@author: ninewolfyan
@email: 821562236@qq.com
"""import numpy as np
import matplotlib.pyplot as plt
import matplotlib#打开文件,并且去掉分隔符
data=[]
f=open(r'C:\Users\user\Desktop\物联网\python 网络爬虫\playerdata1.txt',encoding='UTF-8-sig')#这里为什么用的是'UTF-8-sig',而不是'UTF-8',因为用'UTF-8',打印打开的txt文件会发现最后一行会出现一个标识符,用'UTF-8-sig'可以去掉
fl=f.readlines()
for line in fl:data.append(line.split())#因为这里的data是列表类型,而不是数组或者矩阵,不能用a[:,0]去引用一列,会报错
playername=[x[0] for x in data]
score=[x[1] for x in data]
#score=np.matrix(score)  本来想着将数值列表转成矩阵就可以批量运算了,但好像会报错,行不通
assist=[x[2] for x in data]
#assist=np.matrix(assist)
rebound=[x[3] for x in data]
#rebound=np.matrix(rebound)
steal=[x[4] for x in data]
#steal=np.matrix(steal)
block=[x[5] for x in data]
#block=np.matrix(block)
shootrate=[x[6] for x in data]
#shootrate=np.matrix(shootrate)
threerate=[x[7] for x in data]
#threerate=np.matrix(threerate)
playersnum=len(score)#遍历列表,找出最大值(投篮命中率和三分命中率除外),并计算比值,统一尺寸
def findmax(li):li=liliratio=[]                      #不能直接用li[i]去比较,li[i]是字符串limax=eval(li[0])     #不能直接用eval(li[i])去比较,因为投篮命中率和三分命中率带有百分号,无法比较for i in range(0,playersnum):if eval(li[i])>=limax:limax=eval(li[i])for i in range(0,playersnum):liratio.append(eval(li[i])/limax)return limax,liratio#遍历列表,找出最大值,投篮命中率和三分命中率带有百分号要去除%进行比较,并计算比值
def find1max(li):li=liliratio=[]limax=eval(li[0][0:-1])for i in range(0,playersnum):if eval(li[i][0:-1])>=limax:limax=eval(li[i][0:-1])for i in range(0,playersnum):liratio.append(eval(li[i][0:-1])/limax)return limax,liratioscoremax,scoreratio=findmax(score)
assistmax,assistratio=findmax(assist)
reboundmax,reboundratio=findmax(rebound)
stealmax,stealratio=findmax(steal)
blockmax,blockratio=findmax(block)
shootratemax,shootrateratio=find1max(shootrate)
threeratemax,threerateratio=find1max(threerate)#制作雷达图
def radar(inputname):for i in range(playersnum):if inputname==playername[i]:k=ibreakmatplotlib.rcParams['font.family']='SimHei' #将绘图区域设置成中文字符radar_labels = np.array(['得分', '助攻', '篮板','抢断','盖帽','投篮命中率','三分命中率']) #雷达标签nAttr = 7eachdata=[[scoreratio[k]],[assistratio[k]],[reboundratio[k]],[stealratio[k]],[blockratio[k]],[shootrateratio[k]],[threerateratio[k]],[scoreratio[k]]]angles = np.linspace(0, 2*np.pi, nAttr, endpoint=False)angles = np.concatenate((angles, [angles[0]])) #将angles[0]以行的形式添加到angles的最下方,在末尾添加第一行是为了画出的图形能闭合plt.figure(facecolor="white") #设置画布的底色(除雷达突然以外的画布)ax=plt.subplot(111, polar=True) #将画框设置成圆形雷达图案ax.set_rgrids(np.arange(0,1.2,0.2),'-') #加了这一行后,一定要设置'-',a就没了网格线上的数字了(0.2-1.0)plt.plot(angles,eachdata,'o-',linewidth=1, alpha=0.3) #设置七芒星图案角上的点,alpha为控制透明度plt.fill(angles,eachdata, alpha=0.4) #填充七芒星图案plt.thetagrids(angles*180/np.pi, radar_labels,frac = 1.2) #设置雷达七角上标签plt.figtext(0.5, 1, inputname, ha='center', size=20) #figtext加入文本框,前面两个数字代表位置plt.figtext(0.5,0,'现役球员数据统计(2018-2019赛季)',ha='center',size=15,color='blue')plt.grid(True)plt.savefig('player.jpg')plt.show()#主函数(其实上面打开文件也算主函数,但懒得把上面的代码拿下来了)
inputname=input("请输入球员姓名:")
radar(inputname)

值得注意的点
1.我们存进文件的是按字符串形式存进去的,不能直接用np.loadtxt以矩阵形式提取出来,需要存到列表里,不能直接转成矩阵进行批量运算,而且也不能以a[:,0]的形式去提取一列,会报错,可以用a=(x[0] for x in data的方式提取
2.因为提取出来的是字符串,所以要去掉双引号进行比较
3.雷达图需要我们统一各个数值的大小,所以我们以每个值与最大值的比来表示这个值代表的大小,这里有个容易忽略的点,我们提取的投篮命中率和三分命中率是带有百分号的,无法比较,所以需要去掉百分号,具体方法代码和注释应该解释的很清楚了
4.如果你按照一般雷达图的代码去生成雷达图,会发现网格线上会标有对应的数值,就像,这里的0.2、0.4、0.6一样,但我这七个角代表的数值显然不是0.2之类的,所以强迫症表示很想把它去掉,但是网上关于python雷达图制作系统的参数介绍几乎没有,博主找了好多图,比较了代码才发现这个怎么去掉,具体可以看看代码和注释

我们输入其他球员试试,老詹和球哥

整个实现过程就是这样了,效果达到了,不过还有很大的优化空间,有时间再优化优化,先存着,权当记录和参考

最后,什么都不说了,湖人总冠军!

虎扑球员数据爬取+球员能力分布雷达图相关推荐

  1. python爬取虎扑评论_Python爬取NBA虎扑球员数据

    虎扑是一个认真而有趣的社区,每天有众多JRs在虎扑分享自己对篮球.足球.游戏电竞.运动装备.影视.汽车.数码.情感等一切人和事的见解,热闹.真实.有温度. 受害者地址 https://nba.hupu ...

  2. python爬取虎扑评论_python爬取网站数据

    编码问题 因为涉及到中文,所以必然地涉及到了编码的问题,这一次借这个机会算是彻底搞清楚了. 问题要从文字的编码讲起.原本的英文编码只有0~255,刚好是8位1个字节.为了表示各种不同的语言,自然要进行 ...

  3. python爬取虎扑评论_python爬去虎扑数据信息,完成可视化

    首先分析虎扑页面数据 如图我们所有需要的数据都在其中 ![image.png](1) 所以我们获取需要的内容直接利用beaitifulsoupui4 ``` soup.find_all('a',cla ...

  4. Scrapy爬虫实战—虎扑步行街发帖爬取

    0. 前言 在B站上看了黑马的scrapy,老师讲的超细致,赞! 本文主要用scrapy的基本操作完成爬取,适合入门级学习. 1. scrapy scrapy有很多命令,在terminal输入scra ...

  5. 手机app数据爬取难度等级评估

    一般来说网络数据爬取有两个来源,一个是网页,另一个是移动终端(手机app):随着移动终端的普及和推广,更多的用户甚至已经放弃了网页的访问,因此爬取移动端的数据更为合适. 但是,爬取移动端app数据具有 ...

  6. Python网络数据爬取及分析-智联招聘

    python网络数据爬取及分析-智联招聘 一. 数据爬取 智联招聘是一家面向大型公司和快速发展的中小企业提供一站式专业人力资源的公司,可在智联招聘网站上根据不同城市.不同职位需求搜索得到相关招聘信息. ...

  7. 如何使用Excel完成网站上的数据爬取

    1.数据分析的流程 数据获取:爬取网站上的数据实现可操作性的编辑. 数据处理:数据的预处理,将获取的数据进行格式调整方便后续使用. 常用的Office组件为 Power Query.Power Piv ...

  8. python爬取微博热搜显示到折线图_微博热搜榜前20信息数据爬取进行数据分析与可视化...

    一.设计方案 1.主题式网络爬虫名称:微博热搜榜前20信息数据爬取进行数据分析与可视化 2.爬取内容与数据特征分析:爬取微博热搜榜前20热搜事件.排名与热度,数据呈一定规律排序. 3.设计方案概述:思 ...

  9. 《PYTHON3网络爬虫开发实践》——第六章 Ajax数据爬取

    第六章 Ajax数据爬取 有时候我们在用requests抓取页面的时候,得到的结果可能和在浏览器中看到的不一样:这是因为requests 获取的都是原始的HTML文档,而浏览器中的页面则是经过Java ...

最新文章

  1. ARM的位置无关程序设计在Bootloader中的应用
  2. mysql备份脚本+关_mysql数据库自动定期备份的脚本
  3. OpenStack 对接 Ceph 环境可以创建卷但不能挂载卷的问题
  4. VC菜菜鸟-创建一个即时串口通信程序
  5. bzoj:1666: [Usaco2006 Oct]Another Cow Number Game 奶牛的数字游戏
  6. 堆栈向下增长和向上增长的理解
  7. C#编码规范(3):常用变量和控件在变量命名中缩写
  8. Displaying Bitmaps Efficiently (一)-----Loading Large Bitmaps Efficiently(二)
  9. mybatis简单案例源码详细【注释全面】——测试层(UserMapperTest.java)
  10. 第八节:常见安全隐患和传统的基于Session和Token的安全校验
  11. Redis持久化方式之RDB
  12. 【Python】理解Python(2) - help() 函数? or 类?
  13. pytorch教程之nn.Module类详解——使用Module类来自定义网络层
  14. numpy的array和matrix
  15. bootdo框架介绍使用
  16. 利用Python收发邮件
  17. mysql备份管家婆_管家婆怎么恢复数据,备份数据
  18. python基础知识学完之后再如何学_已学完 Python 基础知识,应该如何继续提升算法能力,以及如何过渡到机器学习?...
  19. codeblocks编辑代码输入法光标无法跟随解决方案
  20. 网络安全—DDoS攻防

热门文章

  1. Dingtalk 发送消息
  2. 利用ArcGIS做一张土地利用现状图
  3. CISP学习资料整理归纳
  4. IDEA 报错 Error:java:错误:不支持发行版本5
  5. 【现代控制理论】| 线性系统的状态空间法
  6. ug五轴编程视频教程
  7. 二维数组求周长的问题
  8. 电力系统潮流计算程序实现C语言版(动态节点+稀疏技术)
  9. 国产WordPress论坛插件-Sliver BBS
  10. Spring 系列:Spring AOP 中@Pointcut的用法(多个Pointcut)