草庐IT

30秒内获取历史所有世界杯的比赛数据 - Python爬虫小实战

也鱼实验室 2023-10-22 原文

2022年卡塔尔世界杯正在如火如荼地进行着,看球时经常听到两队历史交锋数据,突发奇想,要不,用Python来爬一爬历史上所有世界杯的比赛结果,或许这些数据还能帮我们处理一些实际问题?(比如预测?。。)所以这篇文章就来演示一下,如何使用Python和BeautifulSoup来获取世界杯至今(1930-2018)包括当前正在进行的2022年所有比赛结果数据。

安装必要的开源库

这篇文章我们主要使用bs4来爬取网页,用lxml来解析HTML内容,然后使用requests来向目前网页发送请求。
在你的终端上执行以下命令,来安装这些pip包:

$ pip install bs4
$ pip install lxml
$ pip install requests

除了以上三个,我们还需要安装著名的pandas,用来做必要的数据解析:

$ pip install pandas

1. 获取2014年世界杯的数据

这篇文章分成两个部分,第一部分是爬取2014年巴西世界杯的数据,第二部分是把第一部分代码扩展后应用到自1930年开始的所有世界杯比赛数据上。有一点需要注意的是,由于我们将使用维基百科Wikipedia作为数据源,因此需要使python运行的环境有能力访问维基百科,可以使用vpn也可部署在国外服务器上运行,具体方法这里就不细述了。

导入第三方库

首先,导入我们之前安装的库,用以接下来调用。

import pandas as pd
from bs4 import BeautifulSoup
import requests

这里看到我们并不需要import lxml,因为在bs4的关联里已经包含了它。

创建一个Soup

为了能够调用BeautifulSoup,我们首先需要创建一个soup。soup使用lxml解析器来解析HTML的内容。

web = 'https://en.wikipedia.org/wiki/2014_FIFA_World_Cup'
response = requests.get(web)
content = response.text
soup = BeautifulSoup(content, 'lxml')

解析所有的比赛

首先我们要找到不单是一场比赛,而是找到当届世界杯所有比赛结果的网页展现模式。
最简单的方式,我们现在在浏览器里打开2014年世界杯的维基百科网页:
https://en.wikipedia.org/wiki/2014_FIFA_World_Cup
我们可以在网页上任意位置按鼠标右键,在菜单里选择“Inspect”或“检查”,之后浏览器的开发者工具就会显示出来,推荐Chrome或Firefox,工具的界面类似。然后找到以下这个箭头标志,点击它,触发鼠标跟随模式:


接着我们在网页上发现的一个如下模式:
巴西vs克罗地亚的网页结构

可以明显看出,在网页上每一行所代表的一场比赛交锋都包含在图片中蓝色高亮的那条HTML节点之下。
现在我们来用soup中的.find_all方法,它需要两个输入参数:tag name和class name。

matches = soup.find_all('div', class_='footballbox')

通过这句代码我把所有的比赛场次所显示的行,都赋值给了matches。

解析主/客场球队名称和比赛

现在我们需要在matches列表里进行轮询,以解析出每场比赛的具体数据。具体在这篇文章里,我将只解析出双方队名和比分,把他们保存到一个空列表里,方便以后导出到外部表格里。
让我们先来获取主队(home)数据,还是使用网页inspect追踪到主队的名称位置,获取到它的tag name和class name。然后同样的操作在比分(score),以及客队(away)上重复一遍。


爬取巴西队的名称,tag=th,class=fhome

最后,我们用.get_text方法获取到这个类包含的text内容:

home = []
score = []
away = []

for match in matches:
    home.append(match.find('th', class_='fhome').get_text())
    score.append(match.find('th', class_='fscore').get_text())
    away.append(match.find('th', class_='faway').get_text())

用DataFrame存储数据并导出成CSV文件

数据帧(DataFrame)是Python的pandas里好用的数据管理工具,我们为主队,客队和比分建立数据帧对象,此外我们还增加一列year,来代表比赛的年份。

dict_football = {'home': home, 'score': score, 'away': away}
df_football = pd.DataFrame(dict_football)
df_football['year'] = 2014

最后,我们用一句代码,把数据导出到CSV文件里:

df_football.to_csv("fifa_worldcup_historical_data.csv", index=False)

2. 获取所有世界杯比赛数据

在上一章节,我们成功爬取了单届世界杯的数据,通过这种方式,可以很快爬取到每届赛事的数据。首先,我们确认,维基百科的网页链接模式:

https://en.wikipedia.org/wiki/2014_FIFA_World_Cup
https://en.wikipedia.org/wiki/2018_FIFA_World_Cup
https://en.wikipedia.org/wiki/2022_FIFA_World_Cup

可以明显看出,唯一的不同只是URL上的年份,那对我们来说就可以把年份作为变量,赋值给web字符串:

web = f'https://en.wikipedia.org/wiki/{year}_FIFA_World_Cup'

那么接下来只要在代码里动态给year赋值,并循环获取每年的数据就可以了:

import pandas as pd
from bs4 import BeautifulSoup
import requests


def get_matches(year):
    web = f'https://en.wikipedia.org/wiki/{year}_FIFA_World_Cup'
    response = requests.get(web)
    content = response.text
    soup = BeautifulSoup(content, 'lxml')
    matches = soup.find_all('div', class_='footballbox')

    home = []
    score = []
    away = []

    for match in matches:
        home.append(match.find('th', class_='fhome').get_text())
        score.append(match.find('th', class_='fscore').get_text())
        away.append(match.find('th', class_='faway').get_text())

    dict_football = {'home': home, 'score': score, 'away': away}
    df_football = pd.DataFrame(dict_football)
    df_football['year'] = year
    return df_football

初始化years列表,所有年份的世界杯数据就都到手啦。

years = [1930, 1934, 1938, 1950, 1954, 1958, 1962, 1966, 1970, 1974,
         1978, 1982, 1986, 1990, 1994, 1998, 2002, 2006, 2010, 2014,
         2018]

# results: historical data
fifa = [get_matches(year) for year in years]
df_fifa = pd.concat(fifa, ignore_index=True)
df_fifa.to_csv("fifa_worldcup_historical_data.csv", index=False)

当然我们还可以爬取当前正在进行中的2022卡塔尔世界杯的更新数据

df_fixture = get_matches(2022)
df_fixture.to_csv('fifa_worldcup_fixture.csv', index=False)

好了,就这么简单,现在你的电脑里有两个CSV文件了,一个是保存了所有世界杯所有历史对战记录,另一个是2022卡塔尔世界杯当前的数据记录。未来,用同样可以加入更多的数据维度,做更多的相关性研究,或许可以做一个章鱼保罗级别的预测呢,有时间的话,世界杯结束前我会做一期关于用python在做预测的内容。有兴趣的话记得关注!

有关30秒内获取历史所有世界杯的比赛数据 - Python爬虫小实战的更多相关文章

  1. python - 如何使用 Ruby 或 Python 创建一系列高音调和低音调的蜂鸣声? - 2

    关闭。这个问题是opinion-based.它目前不接受答案。想要改进这个问题?更新问题,以便editingthispost可以用事实和引用来回答它.关闭4年前。Improvethisquestion我想在固定时间创建一系列低音和高音调的哔哔声。例如:在150毫秒时发出高音调的蜂鸣声在151毫秒时发出低音调的蜂鸣声200毫秒时发出低音调的蜂鸣声250毫秒的高音调蜂鸣声有没有办法在Ruby或Python中做到这一点?我真的不在乎输出编码是什么(.wav、.mp3、.ogg等等),但我确实想创建一个输出文件。

  2. ruby - 无法在 60 秒内获得稳定的 Firefox 连接 (127.0.0.1 :7055) - 2

    我使用的是Firefox版本36.0.1和Selenium-Webdrivergem版本2.45.0。我能够创建Firefox实例,但无法使用脚本继续进行进一步的操作无法在60秒内获得稳定的Firefox连接(127.0.0.1:7055)错误。有人能帮帮我吗? 最佳答案 我遇到了同样的问题。降级到firefoxv33后一切正常。您可以找到旧版本here 关于ruby-无法在60秒内获得稳定的Firefox连接(127.0.0.1:7055),我们在StackOverflow上找到一个类

  3. Python 相当于 Perl/Ruby ||= - 2

    这个问题在这里已经有了答案:关闭10年前。PossibleDuplicate:Pythonconditionalassignmentoperator对于这样一个简单的问题表示歉意,但是谷歌搜索||=并不是很有帮助;)Python中是否有与Ruby和Perl中的||=语句等效的语句?例如:foo="hey"foo||="what"#assignfooifit'sundefined#fooisstill"hey"bar||="yeah"#baris"yeah"另外,类似这样的东西的通用术语是什么?条件分配是我的第一个猜测,但Wikipediapage跟我想的不太一样。

  4. java - 什么相当于 ruby​​ 的 rack 或 python 的 Java wsgi? - 2

    什么是ruby​​的rack或python的Java的wsgi?还有一个路由库。 最佳答案 来自Python标准PEP333:Bycontrast,althoughJavahasjustasmanywebapplicationframeworksavailable,Java's"servlet"APImakesitpossibleforapplicationswrittenwithanyJavawebapplicationframeworktoruninanywebserverthatsupportstheservletAPI.ht

  5. 世界前沿3D开发引擎HOOPS全面讲解——集3D数据读取、3D图形渲染、3D数据发布于一体的全新3D应用开发工具 - 2

    无论您是想搭建桌面端、WEB端或者移动端APP应用,HOOPSPlatform组件都可以为您提供弹性的3D集成架构,同时,由工业领域3D技术专家组成的HOOPS技术团队也能为您提供技术支持服务。如果您的客户期望有一种在多个平台(桌面/WEB/APP,而且某些客户端是“瘦”客户端)快速、方便地将数据接入到3D应用系统的解决方案,并且当访问数据时,在各个平台上的性能和用户体验保持一致,HOOPSPlatform将帮助您完成。利用HOOPSPlatform,您可以开发在任何环境下的3D基础应用架构。HOOPSPlatform可以帮您打造3D创新型产品,HOOPSSDK包含的技术有:快速且准确的CAD

  6. 华为OD机试用Python实现 -【明明的随机数】 2023Q1A - 2

    华为OD机试题本篇题目:明明的随机数题目输入描述输出描述:示例1输入输出说明代码编写思路最近更新的博客华为od2023|什么是华为od,od薪资待遇,od机试题清单华为OD机试真题大全,用Python解华为机试题|机试宝典【华为OD机试】全流程解析+经验分享,题型分享,防作弊指南华为o

  7. python - 如何读取 MIDI 文件、更改其乐器并将其写回? - 2

    我想解析一个已经存在的.mid文件,改变它的乐器,例如从“acousticgrandpiano”到“violin”,然后将它保存回去或作为另一个.mid文件。根据我在文档中看到的内容,该乐器通过program_change或patch_change指令进行了更改,但我找不到任何在已经存在的MIDI文件中执行此操作的库.他们似乎都只支持从头开始创建的MIDI文件。 最佳答案 MIDIpackage会为您完成此操作,但具体方法取决于midi文件的原始内容。一个MIDI文件由一个或多个音轨组成,每个音轨是十六个channel中任何一个上的

  8. 「Python|Selenium|场景案例」如何定位iframe中的元素? - 2

    本文主要介绍在使用Selenium进行自动化测试或者任务时,对于使用了iframe的页面,如何定位iframe中的元素文章目录场景描述解决方案具体代码场景描述当我们在使用Selenium进行自动化测试的时候,可能会遇到一些界面或者窗体是使用HTML的iframe标签进行承载的。对于iframe中的标签,如果直接查找是无法找到的,会抛出没有找到元素的异常。比如近在咫尺的例子就是,CSDN的登录窗体就是使用的iframe,大家可以尝试通过F12开发者模式查看到的tag_name,class_name,id或者xpath来定位中的页面元素,会抛出NoSuchElementException异常。解决

  9. python ffmpeg 使用 pyav 转换 一组图像 到 视频 - 2

    2022/8/4更新支持加入水印水印必须包含透明图像,并且水印图像大小要等于原图像的大小pythonconvert_image_to_video.py-f30-mwatermark.pngim_dirout.mkv2022/6/21更新让命令行参数更加易用新的命令行使用方法pythonconvert_image_to_video.py-f30im_dirout.mkvFFMPEG命令行转换一组JPG图像到视频时,是将这组图像视为MJPG流。我需要转换一组PNG图像到视频,FFMPEG就不认了。pyav内置了ffmpeg库,不需要系统带有ffmpeg工具因此我使用ffmpeg的python包装p

  10. 牛客网专项练习30天Pytnon篇第02天 - 2

    1.在Python3中,下列关于数学运算结果正确的是:(B)a=10b=3print(a//b)print(a%b)print(a/b)A.3,3,3.3333...B.3,1,3.3333...C.3.3333...,3.3333...,3D.3.3333...,1,3.3333...解析:    在Python中,//表示地板除(向下取整),%表示取余,/表示除(Python2向下取整返回3)2.如下程序Python2会打印多少个数:(D)k=1000whilek>1:    print(k)k=k/2A.1000 B.10C.11D.9解析:    按照题意每次循环K/2,直到K值小于等

随机推荐