前言
qian yan
我想起这个号的密码了
嗯,经过小半年的划水,我终于又想起来还有这个号了,这次的计划是自己做一次基础但是较为详细的足球数据分析,因为方法基本都比较简单,所以准备把这个分析的过程从头到尾的尽可能详细的展示给大家,从最开始的数据爬取,到描述性统计和数据可视化,再到对数据各种建模,包括各类多元统计分析里的方法和机器学习。
这个系列要写什么?
“详细”是什么意思呢,因为说了方法大多数都比较简单,而且其实有些东西也是我第一次接触,所以我会从最开始的数据开始,详细介绍这个数据是怎么从网上用爬虫爬下来的,爬虫过程中的遇到的各种问题以及应对的思路是什么;接着就是数据爬下来后的数据可视化,怎么做出各种好看且能精准、直观的反映数据特征的图表,这些图表各自蕴含了哪些信息;最后就是用各种各样的模型对数据进行分析,比如用聚类可以看看哪些球员可以归为一类,用分类器可以对球员按前锋、中场、后卫进行预测,看看那些被预测错的球员是不是在现实中真的是“非典型”的。
所以整个数据分析的过程会分为好几篇文章,第一篇就是这篇,讲的是怎么用Python把数据从网上爬下来,第二篇会讲描述性统计和数据可视化,而后面的建模会根据效果不错的模型的个数分成1~3篇文章,再立一个flag,争取寒假结束前把这几篇都发出来。。。
这篇文章要写啥?
今天给大家详细介绍一下是怎么用Python在网上爬的数据,以爬FIFA足球游戏网站数据为例。
正文
zheng wen
被迫学爬虫
虽然这是一个案例,不是普适性的完整教程(所以想完全看懂可能需要知道爬虫的基本原理或者对Python的基本功能较熟悉),但是这次爬的网站是一个几乎没有任何反爬虫措施,可以直接在网页源代码中搜索到所有需要的信息的超级友好的网站,所以可以展示最基础的爬虫方式;
而这次爬数据的量较大,网页较多,每个网页上需要爬的数据也较多,而这些数据的格式不尽相同,所以可以尽可能展现不同的搜索+提取数据的方法和思路,并且同一个位置的数据在不同网页里可能在源代码里的位置并不是完全相同,所以大家也可以看到对这种情况的一些处理方法,不过我的处理方法很可能不是最简洁的,会有更简单快捷的方法;
最后,虽然我自己用Python有一段时间了,但是这次是我真正的第一次接触爬虫,之前觉得入门级的爬虫完全是做苦力(当然现在也是这么认为的...),只有投入大量学习时间掌握更多爬虫技巧后才能真正算是一个技术活。但这次确实是很想做这个网站的数据分析,那就顺便学一下吧...
数据源
这次用到的数据是FIFA19这个足球游戏的球员数据网站:
https://sofifa.com/
其实再加入球员的真实比赛数据会更好,但是那个网站(whoscored)有反爬措施,好像那些数据贼贵,可能爬虫高手都不一定爬的下来...加上这个游戏对绝大多数球员的评分是相当准确的,之前这个网站是我玩FIFA经理模式的时候看球员潜力买人用的,后来发现有国外的教授发论文都用这上面的数据!
基本逻辑和准备工作
好了,接下来看看怎么爬这上面的数据,首先打开这个网站,显示的是最热门的100名球员,而我们是要所有球员,所以在左边的条件搜索里不要更改任何搜索条件(默认都是从游戏里能取到的最小值到最大值),直接点“search”,就会按照球员综合能力值从高到低排序排出所有球员,每一页显示61名球员。而点击球员名字后就会进入球员数据的页面,里面的各种数据就是我们要爬取的。
这样,我们的爬虫大致思路就有了:进入数据网站主页→挨个进入球员链接爬取数据→每一页的61名球员爬取完成后进入下一页爬取新的61名球员直到爬取球员数量达到目标。
平台:Python3
所需包:
request、beautifulsoup(爬虫包,尤其是beautifulsoup让爬虫变得更加傻瓜化)
re(正则表达式包,用于爬虫时的数据搜索、提取)
numpy、pandas(Python最常用的包)
time(用于计时)
开始一顿操作吧
好了,现在问题来了,我们怎么让程序去识别我们需要的链接或者数据然后进行提取呢?我们右键点击网页,然后选择“查看源代码”,就会跳出来一个新网页,这里面密密麻麻的东西就是网站开发者编写这个网页时使用的代码,而我们要的所有东西,都在这里面!
所以我们先查看主页的源代码,我们现在是要寻找进入球员数据的链接,而链接的名字是球员的名字,我们就ctrl+F搜索C罗的链接,输入"cristiano",找到一个匹配项,自然就是我们要找的链接了:
我们放大包含"cristiano"的这一段代码,显然我们真正需要的链接只是其中的一小部分,而我们接下来就需要把这段链接提取出来:
所以从代码上,我们首先使用request函数载入网页,然后后面就是beautifulsoup的工作了,先把网页用text形式载入,然后通过①和②定位:
这里讲一下定位。我们载入了网页源代码后会拥有这个网页全部源代码,而我们需要的数据在这个源代码里面,我们需要寻找这个数据的位置,但是我们并不知道这个数据具体是什么,而且不同网站相同位置的数据肯定也不一样,所以我们不能通过数据本身去定位数据的位置,但是这些数据都放在同一种坑里,举个例子,高三有20个班,我们要找这20个班的老师,但是每个老师名字不一样,长相不一样,我们不能通过名字/长相定位到所有老师,但是我们可以通过老师所在的位置:讲台,来定位,所以我们挨个搜索每个教室,讲台上那个人就是老师,准确的来说,坐在讲台正中间的那个人就是老师。
爬虫就是要找那个“讲台”,前面说的①就是所谓的“讲台”,先通过①定位到“讲台”,②就是所谓的“正中间”,这样我们就能精准定位到“老师”。
通过①的定位,一共能定位到122个内容,而第1、3、5、7...121个内容就是那61名球员的链接,这样就能把主页上全部61名球员的链接提取出来,然后通过②定位到具体的链接,最后一个for循环把链接挨个request载入就行了,等这61名球员的数据都提取完了,再载入下一页的球员就行了(当然,这个依次载入每一页的球员列表主页也是一个for循环)。
接下来就是讲解怎么爬球员数据了。这一次不像爬球员链接这么简单了:
从图里可以看到,我们需要的数据散布在网页的各个地方,而这些数据的排版也分成了好几种,而数据本身的形式也是各种各样,最简单的有那一坨能力值,全是数字,其次是一些字符串,比如顺足脚(preferred foot)、声誉(reputation)等等,还有些麻烦的,比如身价,C罗的身价是77M欧,也就是7700万欧,但是比如某位不出名的球员身价是10万欧,那显示出来的就是100K,所以对单位的换算也是需要考虑到的东西。而除了这些数据本身形式的问题,在数据提取过程中也可能会遇到多个数据以及需要的数据和无效字符串连接在了一起,在这里我是使用的字符串分割函数split以及正则表达式来提取我需要的字符串。
经过对需要的数据在源代码中的搜索以及各种尝试,我把所需要的数据分成5批分别进行提取:
①年龄、身高、体重
身高是用的美国人惯用的英尺、英寸,这里我将其换算成了厘米。
体重也是美国人惯用的磅,1磅≈0.91斤,所以磅对我们来说也比较直观,就不换算了。
这一段碰到的问题主要是这三个数据和别的一些字符串连在一起了:
于是我用正则表达式和split函数把这三个数据分别提取了出来。
②位置
即球员在球场上踢的位置(左边锋(LW)、前腰(CAM)、门将(GK)等等)有些球员有多个位置,这里统一只爬球员的第一或唯一位置。
这一段只有这一个数据,而且提取出来不需要剔除掉无用字符串。
③顺足脚、国际声誉、逆足能力、花式技巧
这一段的四个数据也是都被夹在了一大串字符串里,不过用'\n’作为分隔符可以把这四个数据分开,而且每个数据都是在分割出来的子字符串的末尾,这样除了顺足脚是英文单词,需要麻烦一点用正则表达式提取一下,另外三个都直接提取字符串的最后一个字符就行了。
④身价、周薪、进攻/防守积极性、体型、是否真脸、解约金、关注、点赞、点踩
身价(value)和解约金(release)是FIFA游戏根据球员的各种数据自己估算出来的身价,和现实中相比还是有不少误差。
这一段问题主要是身价、周薪、违约金单位可能是M可能是K,需要抓取出来识别之后转换单位。然后其他的数据就很简单了。
⑤各种能力值
这就是球员在游戏里的各项能力值,比如射门力量、加速度之类的,这也算是这次数据中的核心数据了。
这一段的数据抓取出来后有36~38个数据,出现每个球员数据量不同的原因主要就是有些球员没有加入国家队或者没有加入俱乐部,导致他没有所在国家队/俱乐部的实力数据,所以要加入if判断语句判断一共有36、37还是38个数据,然后就是把除了国家队/俱乐部之外的数据挨个导入就行了。
所有问题都解决后,就是写一个很简单的2层for循环爬虫程序了,爬的过程中遇到的唯一的反爬虫措施是爬着爬着会不让你访问,但不会一直禁止,程序因为连接失败中断后,接着已经爬的进度重新运行程序,也能继续爬。我在两台性能差距较大的电脑都试过程序,发现爬的速度差不多,而且爬每个球员数据的时间方差很大(每个球员耗时短则1秒,长则10秒),所以主要还是访问网页的速度造成的,程序本身的运算量可以忽略不计。
最后,经过数次运行程序,终于爬到了一万名球员的数据,将其保存到csv文件里,纯数字的是float或int型数据,有字母的是str型数据,接下来的工作就是下一期----数据可视化啦。
领取专属 10元无门槛券
私享最新 技术干货