关于本站
人大经济论坛-经管之家:分享大学、考研、论文、会计、留学、数据、经济学、金融学、管理学、统计学、博弈论、统计年鉴、行业分析包括等相关资源。
经管之家是国内活跃的在线教育咨询平台!
经管之家新媒体交易平台
提供"微信号、微博、抖音、快手、头条、小红书、百家号、企鹅号、UC号、一点资讯"等虚拟账号交易,真正实现买卖双方的共赢。【请点击这里访问】
TOP热门关键词
扫码加入数据分析学习群 |
在大数据时代,一切都要用数据来说话,大数据处理的过程一般需要经过以下的几个步骤
数据的采集和获取
数据的清洗,抽取,变形和装载
数据的分析,探索和预测
数据的展现
其中首先要做的就是获取数据,并提炼出有效地数据,为下一步的分析做好准备。
数据的来源多种多样,以为我本身是足球爱好者,而世界杯就要来了,所以我就想提取欧洲联赛的数据来做一个分析。许多的网站都提供了详细的足球数据,例如:
网易 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基础,有很多支持的库。这里列出一小部分
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
[size=1em][size=1em]1 | pip install beautifulsoup4 |
我们先从球员的数据开始抓取。
球员数据的Web请求是http://soccerdata.sports.qq.com/playerSearch.aspx?lega=epl&pn=2 ,返回的内容如下图所示:
http://static.open-open.com/lib/uploadImg/20140531/20140531103332_955.png
该web服务有两个参数,lega表示是哪一个联赛,pn表示的是分页的页数。
首先我们先做一些初始化的准备工作
[size=1em][size=1em]1 | from urllib2 import urlopen |
[size=1em]
2 | import urlparse |
[size=1em]
3 | import bs4 |
[size=1em]
4 |
[size=1em]
5 | BASE_URL = "http://soccerdata.sports.qq.com" |
[size=1em]
6 | PLAYER_LIST_QUERY = "/playerSearch.aspx?lega=%s&pn=%d" |
[size=1em]
7 | league = ['epl','seri','bund','liga','fran','scot','holl','belg'] |
[size=1em]
8 | page_number_limit = 100 |
[size=1em]
9 | 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是我们会用到的一些常量。
下面是抓取球员数据的具体代码:
[size=1em][size=1em]01 | def get_players(baseurl): |
[size=1em]
02 | html = urlopen(baseurl).read() |
[size=1em]
03 | soup = bs4.BeautifulSoup(html, "lxml") |
[size=1em]
04 | players = [ dd for dd in soup.select('.searchResult tr') if dd.contents[1].name != 'th'] |
[size=1em]
05 | result = [] |
[size=1em]
06 | for player in players: |
[size=1em]
07 | record = [] |
[size=1em]
08 | link = '' |
[size=1em]
09 | query = [] |
[size=1em]
10 | for item in player.contents: |
[size=1em]
11 | if type(item) is bs4.element.Tag: |
[size=1em]
12 | if not item.string and item.img: |
[size=1em]
13 | record.append(item.img['src']) |
[size=1em]
14 | else : |
[size=1em]
15 | record.append(item.string and item.string.strip() or 'na') |
[size=1em]
16 | try: |
[size=1em]
17 | o = urlparse.urlparse(item.a['href']).query |
[size=1em]
18 | if len(link) == 0: |
[size=1em]
19 | link = o |
[size=1em]
20 | query = dict([(k,v[0]) for k,v in urlparse.parse_qs(o).items()]) |
[size=1em]
21 | except: |
[size=1em]
22 | pass |
[size=1em]
23 |
|
[size=1em]
24 | if len(record) != 10: |
[size=1em]
25 | for i in range(0, 10 - len(record)): |
[size=1em]
26 | record.append('na') |
[size=1em]
27 | record.append(unicode(link,'utf-8')) |
[size=1em]
28 | record.append(unicode(query["id"],'utf-8')) |
[size=1em]
29 | record.append(unicode(query["teamid"],'utf-8')) |
[size=1em]
30 | record.append(unicode(query["lega"],'utf-8')) |
[size=1em]
31 | result.append(record) |
[size=1em]
32 | return result |
[size=1em]
33 |
|
[size=1em]
34 | result = [] |
[size=1em]
35 | for url in [ BASE_URL + PLAYER_LIST_QUERY % (l,n) for l in league for n in range(page_number_limit) ]: |
[size=1em]
36 | result = result +get_players(url) |
我们来看看抓取球员数据的详细过程:
首先我们定义了一个get_players方法,该方法会返回某一请求页面上所有球员的数据。为了得到所有的数据,我们通过一个for循环,因为要循环各个联赛,每个联赛又有多个分页,一般情况下是需要一个双重循环的:
[size=1em][size=1em]1 | for i in league: |
[size=1em]
2 | for j in range(0, 100): |
[size=1em]
3 | url = BASE_URL + PLAYER_LIST_QUERY % (l,n) |
[size=1em]
4 | ## 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'>,我们使用以下方式来查找:
[size=1em][size=1em]1 | obj = soup.find("xx","cc") |
另外一种常见的方式就是通过CSS的selector方式,在上述代码中,我们选择class=searchResult元素里面,所有的tr元素,过滤掉th也就是表头元素。
[size=1em][size=1em]1 | for dd in soup.select('.searchResult tr') if dd.contents[1].name != 'th' |
http://static.open-open.com/lib/uploadImg/20140531/20140531103332_76.png
对于每一行记录tr,生成一条球员记录,并存放在一个列表中。所以我们就循环tr的内容tr.contents,获得对应的field内容。
对于每一个tr的content,我们先检查其类型是不是一个Tag,对于Tag类型有几种情况,一种是包含img的情况,我们需要取出球员的头像图片的网址。
http://static.open-open.com/lib/uploadImg/20140531/20140531103332_18.png
另一种是包含了一个链接,指向其他数据内容
http://static.open-open.com/lib/uploadImg/20140531/20140531103332_721.png
所以在代码中要分别处理这些不同的情况。
对于一个Tag对象,Tag.x可以获得他的子对象,Tag['x']可以获得Tag的attribute的值。
所以用item.img['src']可以获得item的子元素img的src属性。
对已包含链接的情况,我们通过urlparse来获取查询url中的参数。这里我们利用了dict comprehension的把查询参数放入一个dict中,然后添加到列表中。
[size=1em][size=1em]1 | 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则用空值填充,目的是避免一些不一致的地方。
[size=1em][size=1em]1 | if len(record) != 10: |
[size=1em]
2 | for i in range(0, 10 - len(record)): |
[size=1em]
3 | record.append('na') |
最后,我们把query中的一些相关的参数如球员的id,球队的id,所在的联赛代码等加入到列表。
[size=1em][size=1em]1 | record.append(unicode(link,'utf-8')) |
[size=1em]
2 | record.append(unicode(query["id"],'utf-8')) |
[size=1em]
3 | record.append(unicode(query["teamid"],'utf-8')) |
[size=1em]
4 | record.append(unicode(query["lega"],'utf-8')) |
最后我们把本页面所有球员的列表放入一个列表返回。
好了,现在我们拥有了一个包含所有球员的信息的列表,我们需要把它存下来,以进一步的处理,分析。通常,csv格式是一个常见的选择。
[size=1em][size=1em]01 | import csv |
[size=1em]
02 | def write_csv(filename, content, header = None): |
[size=1em]
03 | file = open(filename, "wb") |
[size=1em]
04 | file.write('\xEF\xBB\xBF') |
[size=1em]
05 | writer = csv.writer(file, delimiter=',') |
[size=1em]
06 | if header: |
[size=1em]
07 | writer.writerow(header) |
[size=1em]
08 | for row in content: |
[size=1em]
09 | encoderow = [dd.encode('utf8') for dd in row] |
[size=1em]
10 | writer.writerow(encoderow) |
[size=1em]
11 |
[size=1em]
12 | write_csv('players.csv',result,player_fields) |
这里需要注意的就是关于encode的问题。因为我们使用的时utf-8的编码方式,在csv的文件头,需要写入\xEF\xBB\xBF,详见这篇文章
好了现在大功告成,抓取的csv如下图:
http://static.open-open.com/lib/uploadImg/20140531/20140531103332_207.png
因为之前我们还抓取了球员本赛季的比赛详情,所以我们可以进一步的抓取所有球员每一场比赛的记录
http://static.open-open.com/lib/uploadImg/20140531/20140531103332_348.png
抓取的代码如下
[size=1em][size=1em]01 | def get_player_match(url): |
[size=1em]
02 | html = urlopen(url).read() |
[size=1em]
03 | soup = bs4.BeautifulSoup(html, "lxml") |
[size=1em]
04 | matches = [ dd for dd in soup.select('.shtdm tr') if dd.contents[1].name != 'th'] |
[size=1em]
05 | records = [] |
[size=1em]
06 | for item in [ dd for dd in matches if len(dd.contents) > 11]: ## filter out the personal part |
[size=1em]
07 | record = [] |
[size=1em]
08 | for match in [ dd for dd in item.contents if type(dd) is bs4.element.Tag]: |
[size=1em]
09 | if match.string: |
[size=1em]
10 | record.append(match.string) |
[size=1em]
11 | else: |
[size=1em]
12 | for d in [ dd for dd in match.contents if type(dd) is bs4.element.Tag]: |
[size=1em]
13 | query = dict([(k,v[0]) for k,v in urlparse.parse_qs(d['href']).items()]) |
[size=1em]
14 | record.append('teamid' in query and query['teamid'] or query['id']) |
[size=1em]
15 | record.append(d.string and d.string or 'na') |
[size=1em]
16 | records.append(record) |
[size=1em]
17 | return records[1:]##remove the first record as the header |
[size=1em]
18 |
[size=1em]
19 | def get_players_match(playerlist, baseurl = BASE_URL + '/player.aspx?'): |
[size=1em]
20 | result = [] |
[size=1em]
21 | for item in playerlist: |
[size=1em]
22 | url =baseurl + item[10] |
[size=1em]
23 | print url |
[size=1em]
24 | result = result + get_player_match(url) |
[size=1em]
25 | return result |
[size=1em]
26 | 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'] |
[size=1em]
27 | write_csv('m.csv',get_players_match(result),match_fields) |
抓取的过程和之前类似。
下一步做什么现在我们拥有了详细的欧洲联赛的数据,那么下一步要怎么做呢,我推荐大家把数据导入BI工具来做进一步的分析。有两个比较好的选择:
Tableau Public
Tableau在数据可视化领域可谓无出其右,Tableau Public完全免费,用数据可视化来驱动数据的探索和分析,拥有非常好的用户体验
Splunk
Splunk提供一个大数据的平台,主要面向机器数据。支持每天免费导入500M的数据,如果是个人学习,应该足够了。
当然你也可以用Excel。
来自:http://my.oschina.net/taogang/blog/271060
免流量费下载资料----在经管之家app可以下载论坛上的所有资源,并且不额外收取下载高峰期的论坛币。
涵盖所有经管领域的优秀内容----覆盖经济、管理、金融投资、计量统计、数据分析、国贸、财会等专业的学习宝库,各类资料应有尽有。
来自五湖四海的经管达人----已经有上千万的经管人来到这里,你可以找到任何学科方向、有共同话题的朋友。
经管之家(原人大经济论坛),跨越高校的围墙,带你走进经管知识的新世界。
扫描下方二维码下载并注册APP
您可能感兴趣的文章
人气文章
本文标题:使用Python抓取欧洲足球联赛数据进行大数据分析
本文链接网址:https://bbs.pinggu.org/jg/ruanjianpeixun_shujufenxipeixun_3089239_1.html
2.转载的文章仅代表原创作者观点,与本站无关。其原创性以及文中陈述文字和内容未经本站证实,本站对该文以及其中全部或者部分内容、文字的真实性、完整性、及时性,不作出任何保证或承若;
3.如本站转载稿涉及版权等问题,请作者及时联系本站,我们会及时处理。