使用Python抓取欧洲足球联赛数据 python抓球问题
off999 2024-12-16 15:20 25 浏览 0 评论
背景
Web Scraping
在大数据时代,一切都要用数据来说话,大数据处理的过程一般需要经过以下的几个步骤
- 数据的采集和获取
- 数据的清洗,抽取,变形和装载
- 数据的分析,探索和预测
- 数据的展现
其中首先要做的就是获取数据,并提炼出有效地数据,为下一步的分析做好准备。
数据的来源多种多样,以为我本身是足球爱好者,而世界杯就要来了,所以我就想提取欧洲联赛的数据来做一个分析。许多的网站都提供了详细的足球数据,例如:
- 网易 http://goal.sports.163.com/
- 腾讯体育 http://soccerdata.sports.qq.com/
- 虎扑体育 http://soccer.hupu.com/
- http://www.football-data.co.uk/
这些网站都提供了详细的足球数据,然而为了进一步的分析,我们希望数据以格式化的形式存储,那么如何把这些网站提供的网页数据转换成格式化的数据呢?这就要用到Web scraping的技术了。简单地说,Web Scraping就是从网站抽取信息, 通常利用程序来模拟人浏览网页的过程,发送http请求,从http响应中获得结果。
Web Scraping 注意事项
在抓取数据之前,要注意以下几点:
- 阅读网站有关数据的条款和约束条件,搞清楚数据的拥有权和使用限制
- 友好而礼貌,使用计算机发送请求的速度飞人类阅读可比,不要发送非常密集的大量请求以免造成服务器压力过大
- 因为网站经常会调整网页的结构,所以你之前写的Scraping代码,并不总是能够工作,可能需要经常调整
- 因为从网站抓取的数据可能存在不一致的情况,所以很有可能需要手工调整
Python Web Scraping 相关的库
Python提供了很便利的Web Scraping基础,有很多支持的库。这里列出一小部分
- BeautifulSoup http://www.crummy.com/software/BeautifulSoup/
- Scrapy http://scrapy.org/
- webscraping https://code.google.com/p/webscraping/
- pyquery https://pypi.python.org/pypi/pyquery
当然也不一定要用Python或者不一定要自己写代码,推荐关注import.io
Web Scraping 代码
下面,我们就一步步地用Python,从腾讯体育来抓取欧洲联赛13/14赛季的数据。
首先要安装Beautifulsoup
pip install beautifulsoup4
我们先从球员的数据开始抓取。
球员数据的Web请求是http://soccerdata.sports.qq.com/playerSearch.aspx?lega=epl&pn=2 ,返回的内容如下图所示:
该web服务有两个参数,lega表示是哪一个联赛,pn表示的是分页的页数。
首先我们先做一些初始化的准备工作
from urllib2 import urlopen import urlparse import bs4 BASE_URL = "http://soccerdata.sports.qq.com" PLAYER_LIST_QUERY = "/playerSearch.aspx?lega=%s&pn=%d" league = ['epl','seri','bund','liga','fran','scot','holl','belg'] page_number_limit = 100 player_fields = ['league_cn','img','name_cn','name','team','age','position_cn','nation','birth','query','id','teamid','league']
urlopen,urlparse,bs4是我们将要使用的Python库。
BASE_URL,PLAYER_LIST_QUERY,league,page_number_limit和player_fields是我们会用到的一些常量。
下面是抓取球员数据的具体代码:
def get_players(baseurl):
html = urlopen(baseurl).read()
soup = bs4.BeautifulSoup(html, "lxml")
players = [ dd for dd in soup.select('.searchResult tr') if dd.contents[1].name != 'th']
result = []
for player in players:
record = []
link = ''
query = []
for item in player.contents:
if type(item) is bs4.element.Tag:
if not item.string and item.img:
record.append(item.img['src'])
else :
record.append(item.string and item.string.strip() or 'na')
try:
o = urlparse.urlparse(item.a['href']).query
if len(link) == 0:
link = o
query = dict([(k,v[0]) for k,v in urlparse.parse_qs(o).items()])
except:
pass
if len(record) != 10:
for i in range(0, 10 - len(record)):
record.append('na')
record.append(unicode(link,'utf-8'))
record.append(unicode(query["id"],'utf-8'))
record.append(unicode(query["teamid"],'utf-8'))
record.append(unicode(query["lega"],'utf-8'))
result.append(record)
return result
result = []
for url in [ BASE_URL + PLAYER_LIST_QUERY % (l,n) for l in league for n in range(page_number_limit) ]:
result = result + get_players(url)我们来看看抓取球员数据的详细过程:
首先我们定义了一个get_players方法,该方法会返回某一请求页面上所有球员的数据。为了得到所有的数据,我们通过一个for循环,因为要循环各个联赛,每个联赛又有多个分页,一般情况下是需要一个双重循环的:
for i in league: for j in range(0, 100): url = BASE_URL + PLAYER_LIST_QUERY % (l,n) ## send request to url and do scraping
Python的list comprehension可以很方便的通过构造一个列表的方式来减少循环的层次。
另外Python还有一个很方便的语法来合并连个列表: list = list1 + list2
好我们再看看如何使用BeautifulSoup来抓取网页中我们需要的内容。
首先调用urlopen读取对应url的内容,通常是一个html,用该html构造一个beautifulsoup对象。
beautifulsoup对象支持很多查找功能,也支持类似css的selector。通常如果有一个DOM对象是<xx class='cc'>,我们使用以下方式来查找:
obj = soup.find("xx","cc")另外一种常见的方式就是通过CSS的selector方式,在上述代码中,我们选择class=searchResult元素里面,所有的tr元素,过滤掉th也就是表头元素。
for dd in soup.select('.searchResult tr') if dd.contents[1].name != 'th'对于每一行记录tr,生成一条球员记录,并存放在一个列表中。所以我们就循环tr的内容tr.contents,获得对应的field内容。
对于每一个tr的content,我们先检查其类型是不是一个Tag,对于Tag类型有几种情况,一种是包含img的情况,我们需要取出球员的头像图片的网址。
另一种是包含了一个链接,指向其他数据内容
所以在代码中要分别处理这些不同的情况。
对于一个Tag对象,Tag.x可以获得他的子对象,Tag['x']可以获得Tag的attribute的值。
所以用item.img['src']可以获得item的子元素img的src属性。
对已包含链接的情况,我们通过urlparse来获取查询url中的参数。这里我们利用了dict comprehension的把查询参数放入一个dict中,然后添加到列表中。
dict([(k,v[0]) for k,v in urlparse.parse_qs(o).items()])
对于其它情况,我们使用Python 的and or表达式以确保当Tag的内容为空时,我们写入‘na’,该表达式类似C/C++或Java中的三元操作符 X ? A : B
然后有一段代码判断当前记录的长度是否大于10,不大于10则用空值填充,目的是避免一些不一致的地方。
if len(record) != 10:
for i in range(0, 10 - len(record)):
record.append('na')最后,我们把query中的一些相关的参数如球员的id,球队的id,所在的联赛代码等加入到列表。
record.append(unicode(link,'utf-8')) record.append(unicode(query["id"],'utf-8')) record.append(unicode(query["teamid"],'utf-8')) record.append(unicode(query["lega"],'utf-8'))
最后我们把本页面所有球员的列表放入一个列表返回。
好了,现在我们拥有了一个包含所有球员的信息的列表,我们需要把它存下来,以进一步的处理,分析。通常,csv格式是一个常见的选择。
import csv
def write_csv(filename, content, header = None):
file = open(filename, "wb")
file.write('\xEF\xBB\xBF')
writer = csv.writer(file, delimiter=',')
if header:
writer.writerow(header)
for row in content:
encoderow = [dd.encode('utf8') for dd in row]
writer.writerow(encoderow)
write_csv('players.csv',result,player_fields)这里需要注意的就是关于encode的问题。因为我们使用的时utf-8的编码方式,在csv的文件头,需要写入\xEF\xBB\xBF,详见这篇文章
好了现在大功告成,抓取的csv如下图:
因为之前我们还抓取了球员本赛季的比赛详情,所以我们可以进一步的抓取所有球员每一场比赛的记录
抓取的代码如下
def get_player_match(url):
html = urlopen(url).read()
soup = bs4.BeautifulSoup(html, "lxml")
matches = [ dd for dd in soup.select('.shtdm tr') if dd.contents[1].name != 'th']
records = []
for item in [ dd for dd in matches if len(dd.contents) > 11]: ## filter out the personal part
record = []
for match in [ dd for dd in item.contents if type(dd) is bs4.element.Tag]:
if match.string:
record.append(match.string)
else:
for d in [ dd for dd in match.contents if type(dd) is bs4.element.Tag]:
query = dict([(k,v[0]) for k,v in urlparse.parse_qs(d['href']).items()])
record.append('teamid' in query and query['teamid'] or query['id'])
record.append(d.string and d.string or 'na')
records.append(record)
return records[1:] ##remove the first record as the header
def get_players_match(playerlist, baseurl = BASE_URL + '/player.aspx?'):
result = []
for item in playerlist:
url = baseurl + item[10]
print url
result = result + get_player_match(url)
return result
match_fields = ['date_cn','homeid','homename_cn','matchid','score','awayid','awayname_cn','league_cn','firstteam','playtime','goal','assist','shoot','run','corner','offside','foul','violation','yellowcard','redcard','save']
write_csv('m.csv',get_players_match(result),match_fields)抓取的过程和之前类似。
下一步做什么
现在我们拥有了详细的欧洲联赛的数据,那么下一步要怎么做呢,我推荐大家把数据导入BI工具来做进一步的分析。有两个比较好的选择:
- Tableau Public
Tableau在数据可视化领域可谓无出其右,Tableau Public完全免费,用数据可视化来驱动数据的探索和分析,拥有非常好的用户体验
- Splunk
Splunk提供一个大数据的平台,主要面向机器数据。支持每天免费导入500M的数据,如果是个人学习,应该足够了。
当然你也可以用Excel。 另外大家如果有什么好的免费的数据分析的平台,欢迎交流。
相关推荐
- 阿里云国际站ECS:阿里云ECS如何提高网站的访问速度?
-
TG:@yunlaoda360引言:速度即体验,速度即业务在当今数字化的世界中,网站的访问速度已成为决定用户体验、用户留存乃至业务转化率的关键因素。页面加载每延迟一秒,都可能导致用户流失和收入损失。对...
- 高流量大并发Linux TCP性能调优_linux 高并发网络编程
-
其实主要是手里面的跑openvpn服务器。因为并没有明文禁p2p(哎……想想那么多流量好像不跑点p2p也跑不完),所以造成有的时候如果有比较多人跑BT的话,会造成VPN速度急剧下降。本文所面对的情况为...
- 性能测试100集(12)性能指标资源使用率
-
在性能测试中,资源使用率是评估系统硬件效率的关键指标,主要包括以下四类:#性能测试##性能压测策略##软件测试#1.CPU使用率定义:CPU处理任务的时间占比,计算公式为1-空闲时间/总...
- Linux 服务器常见的性能调优_linux高性能服务端编程
-
一、Linux服务器性能调优第一步——先搞懂“看什么”很多人刚接触Linux性能调优时,总想着直接改配置,其实第一步该是“看清楚问题”。就像医生看病要先听诊,调优前得先知道服务器“哪里...
- Nginx性能优化实战:手把手教你提升10倍性能!
-
关注△mikechen△,十余年BAT架构经验倾囊相授!Nginx是大型架构而核心,下面我重点详解Nginx性能@mikechen文章来源:mikechen.cc1.worker_processe...
- 高并发场景下,Spring Cloud Gateway如何抗住百万QPS?
-
关注△mikechen△,十余年BAT架构经验倾囊相授!大家好,我是mikechen。高并发场景下网关作为流量的入口非常重要,下面我重点详解SpringCloudGateway如何抗住百万性能@m...
- Kubernetes 高并发处理实战(可落地案例 + 源码)
-
目标场景:对外提供HTTPAPI的微服务在短时间内收到大量请求(例如每秒数千至数万RPS),要求系统可弹性扩容、限流降级、缓存减压、稳定运行并能自动恢复。总体思路(多层防护):边缘层:云LB...
- 高并发场景下,Nginx如何扛住千万级请求?
-
Nginx是大型架构的必备中间件,下面我重点详解Nginx如何实现高并发@mikechen文章来源:mikechen.cc事件驱动模型Nginx采用事件驱动模型,这是Nginx高并发性能的基石。传统...
- Spring Boot+Vue全栈开发实战,中文版高清PDF资源
-
SpringBoot+Vue全栈开发实战,中文高清PDF资源,需要的可以私我:)SpringBoot致力于简化开发配置并为企业级开发提供一系列非业务性功能,而Vue则采用数据驱动视图的方式将程序...
- Docker-基础操作_docker基础实战教程二
-
一、镜像1、从仓库获取镜像搜索镜像:dockersearchimage_name搜索结果过滤:是否官方:dockersearch--filter="is-offical=true...
- 你有空吗?跟我一起搭个服务器好不好?
-
来人人都是产品经理【起点学院】,BAT实战派产品总监手把手系统带你学产品、学运营。昨天闲的没事的时候,随手翻了翻写过的文章,发现一个很严重的问题。就是大多数时间我都在滔滔不绝的讲理论,却很少有涉及动手...
- 部署你自己的 SaaS_saas如何部署
-
部署你自己的VPNOpenVPN——功能齐全的开源VPN解决方案。(DigitalOcean教程)dockovpn.io—无状态OpenVPNdockerized服务器,不需要持久存储。...
- Docker Compose_dockercompose安装
-
DockerCompose概述DockerCompose是一个用来定义和管理多容器应用的工具,通过一个docker-compose.yml文件,用YAML格式描述服务、网络、卷等内容,...
- 京东T7架构师推出的电子版SpringBoot,从构建小系统到架构大系统
-
前言:Java的各种开发框架发展了很多年,影响了一代又一代的程序员,现在无论是程序员,还是架构师,使用这些开发框架都面临着两方面的挑战。一方面是要快速开发出系统,这就要求使用的开发框架尽量简单,无论...
- Kubernetes (k8s) 入门学习指南_k8s kubeproxy
-
Kubernetes(k8s)入门学习指南一、什么是Kubernetes?为什么需要它?Kubernetes(k8s)是一个开源的容器编排系统,用于自动化部署、扩展和管理容器化应用程序。它...
欢迎 你 发表评论:
- 一周热门
- 最近发表
- 标签列表
-
- python计时 (73)
- python安装路径 (56)
- python类型转换 (93)
- python进度条 (67)
- python吧 (67)
- python的for循环 (65)
- python格式化字符串 (61)
- python静态方法 (57)
- python列表切片 (59)
- python面向对象编程 (60)
- python 代码加密 (65)
- python串口编程 (77)
- python封装 (57)
- python写入txt (66)
- python读取文件夹下所有文件 (59)
- python操作mysql数据库 (66)
- python获取列表的长度 (64)
- python接口 (63)
- python调用函数 (57)
- python多态 (60)
- python匿名函数 (59)
- python打印九九乘法表 (65)
- python赋值 (62)
- python异常 (69)
- python元祖 (57)
