爬取欧洲杯射手榜球员排名以及各项数据

一、主题式网络爬虫设计方案(15分)

1.爬虫名称

  爬取欧洲杯射手榜排名以及各项数据

2.主题式网络爬虫爬取的内容与数据特征分析

  爬取内容:爬取网页欧洲杯射手榜排名、名字、球队、点球、次数、时间、射门、射正。

  数据分析:各球员的排名与其各项数据整体呈现的趋势,可通过后续绘制直方图、折线图等观察数据的变化情况。

3.主题式网络爬虫设计方案概述(包括实现思路与技术难点)

  访问网页得到状态码,分析网页源代码,找出所需要的的标签,逐个提取标签保存到相同路径csv文件中,读取改文件,进行数据清洗,数据模型分析,数据可视化处理,绘制分布图,用最小二乘法分析两个变量间的二次拟合方程和绘制拟合曲线。

  技术难点:做数据分析,即求回归系数,在爬取网页数据,提取数据成csv文件时,由于数据较为杂乱,对动态网站的数据获取的URL难发现、所要的爬取的数据分布在网页的不同深度。由于不明原因,输出结果经常会显示超出列表范围。

二、主题页面的结构特征分析(15分)

1.主题页面的结构特征

  (1)该网站的表单属于后台js提交的方式,在该网站的地址栏下所显示的html标签内容中没有显示我们想要的数据,针对动态网页的爬取,先在选择栏选择“欧洲杯射手榜”,显示了欧洲杯射手的榜单,通过分析,所爬取目标数据分布页面的不同深度。

   (2)采用页面审查元素,通过网络类别中XHR获取到了我们所需要的URL,

   (3)点击该URL再点击右侧的Headers发现了目标爬取网页的完整URL,可通过requests库进行爬取。

2.Htmls页面解析

  在这个所获得的完整URL中,发现‘player?cid=45’中‘player’是我们所搜索的内容,‘type=1’中‘1’是页面的类别,通过这两者的关系可以控制搜索参数和页面的深度,编写迭代程序实现对其循环访问。

 3.节点(标签)查找方法与遍历方法

  将上述的链接(http://api.sports.163.com/base/cs/union/player?cid=45&type=1)打开,显示如下:

 三、网络爬虫程序设计(60分)

爬虫程序主体要包括以下各部分,要附源代码及较详细注释,并在每部分程序后面提供输出结果的截图。

 1.数据爬取与采集

 1 #网易足球欧洲杯数据分析,爬取网页内容
 2 #获取信息
 3 import requests
 4 from bs4 import BeautifulSoup
 5 import json
 6 import pandas as pd
 7 #搜寻网页
 8 r=requests.get('http://api.sports.163.com/base/cs/union/player?cid=45&type=1')
 9 r.encoding="utf-8"
10 data=json.loads(r.text)
11 a=data['data']
12 #遍历网页中的数据
13 for i in a:
14     print(i)
15 #输出数据

输出结果:

  #采集数据

 1 #创建一个序列空列表
 2 b=[]
 3 for i in range(1,51):
 4     b.append(i)
 5 print(b)
 6 #创建各个数据的空表
 7 a=data['data']
 8 attPenGoal=[]#点球
 9 goals=[]#进球
10 names=[]#名字
11 team=[]#球队
12 ontargetScoringAtt=[]#射正
13 minsPlayed=[]#出场时间
14 games=[]#次数
15 totalScoringAtt=[]#射门
16 playerId=[]#队员编号
17 teamId=[]#球队编号
18 #每个数据都遍历循环
19 for i in a:
20     attPenGoal.append(i['attPenGoal'])
21     goals.append(i['goals'])
22     names.append(i['player'])
23     games.append(i['games'])
24     totalScoringAtt.append(i['totalScoringAtt'])
25     team.append(i['team'])
26     ontargetScoringAtt.append(i['ontargetScoringAtt'])
27     minsPlayed.append(i['minsPlayed'])
28     playerId.append(i['playerId'])
29     teamId.append(i['teamId'])
30 #导出各项数据
31 df=pd.DataFrame({
32                  '排名':b,
33                  '名字':names, 
34                  '球队':team,
35                  '次数':games,
36                  '点球':goals,
37                  '射门':totalScoringAtt,
38                  '射正':ontargetScoringAtt,
39                  '出场时间':minsPlayed,
40                  '队员编号':playerId,
41                  '球队编号':teamId
42                 })
43 #存入足球数据的txt文本中
44 df.to_csv('E:\爬虫\足球数据.txt',index=False)
45 #插入下列数据
46 df['射正']=ontargetScoringAtt
47 df['出场时间']=minsPlayed
48 df['队员编号']=playerId
49 df['球队编号']=teamId
50 #将文本数据变为csv表格数据
51 df.to_csv('E:\爬虫\足球数据.csv',index=False)
52 
53 #插入排名数据
54 df['排名']=b
55 df.to_csv('E:\爬虫\足球数据.csv',index=True)

 

2.对数据进行清洗和处理 

1 #检查并显示重复值
2 print(df.duplicated())

 

 #检查是否有空值

1 #检查是否有空值
2 print(df['点球'].isnull().value_counts())

 

 3.文本分析(可选):jieba分词、wordcloud可视化
4.数据分析与可视化
(例如:数据柱形图、直方图、散点图、盒图、分布图、数据回归分析等)

 1 #绘制柱状图
 2 import pandas as pd
 3 import numpy as np
 4 import matplotlib.pyplot as plt
 5 plt.rcParams['font.sans-serif']=['SimHei'] 
 6 #用来正常显示中文标签
 7 a = df.排名
 8 b = df.点球
 9 plt.bar(a,b, color='red')
10 plt.xlabel("排名")
11 #横坐标为排名
12 plt.ylabel("点球")
13 #纵坐标为点球
14 plt.title('欧洲射手榜')
15 plt.show()

 

 

 1 #绘制散点图
 2 import matplotlib.pyplot as plt
 3 plt.rcParams['font.sans-serif']=['SimHei'] #用于正常显示中文标签
 4 size=50
 5 #调整大小
 6 plt.xlabel("排名")
 7 plt.ylabel("点球")
 8 #横坐标为排名,纵坐标为点球
 9 plt.title('欧洲射手榜')
10 #表头是“欧洲射手榜”
11 a = df.排名
12 b = df.点球
13 plt.scatter(a,b,size, color="g", marker='.')
14 plt.show

 

 

 1 #绘制射正与排名堆叠图
 2 import pandas as pd
 3 import numpy as np
 4 import matplotlib.pyplot as plt
 5 plt.rcParams['font.sans-serif']=['SimHei']
 6 plt.rcParams['axes.unicode_minus'] = False   # 用来正常显示负号
 7 plt.stackplot(df.射正, df.排名, color=['b',])
 8 plt.xlabel("射正")
 9 plt.ylabel("排名")
10 plt.title('射正与排名堆叠图')
11 plt.show()

 

 

1 #绘制折线图
2 plt.rcParams['font.sans-serif']=['SimHei'] #用来正常显示中文标签
3 a = df.排名
4 b = df.射正
5 plt.plot(a,b, color='r')
6 plt.xlabel("排名")
7 plt.ylabel("射正")
8 plt.title('排名与射正数据折线图')
9 plt.show()

 

 

 1 #绘制回归图
 2 import seaborn as sns
 3 plt.rcParams['font.sans-serif']=['SimHei'] #用来正常显示中文标签
 4 a = df.排名
 5 b = df.射正
 6 sns.regplot(a,b,color='g')
 7 plt.xlabel("排名")
 8 plt.ylabel("射正")
 9 plt.title('排名与射正数据回归图')
10 plt.show()

 

 

 1 #绘画扇形饼状图
 2 from collections import Counter
 3 import matplotlib.pyplot as plt
 4 import matplotlib as mpt
 5 mpt.rcParams['font.family']='fangsong'
 6 oses = {
 7 '意大利':22.37,
 8 '丹麦': 20.31,
 9 '英格兰': 16.28,
10 '比利时': 10.73,
11 '西班牙': 12.25,
12 '其他':18.06
13 
14 }
15 names = oses.keys()
16 percents = oses.values()
17 patches,texts,autotexts = plt.pie(percents,labels=names,autopct="%.2f%%",explode=(0,0.05,0,0,0,0))
18 for text in texts+autotexts:
19     plt.setp(text,fontproperties=font)
20     text.set_fontsize(10)
21 for text in autotexts:
22     text.set_color("white")

 

  通过以上的分析,我们可以发现在排名与一些其他数据的比较之中,呈现出起伏的变化,可以得知一些场均得分排在前面的球员,在各项数据以及场均能得到的较高的射正没有比排在他们之后的一些球员高。从现实上的比赛来看,出手数对得分起到了一定的影响,导致场均得分较低。 

#回归线性分析、拟合曲线

 1 #绘制线性回归,拟合曲线
 2 import matplotlib.pyplot as plt
 3 
 4 import matplotlib
 5 
 6 import numpy as np
 7 
 8 import scipy.optimize as opt
 9 
10 import csv
11 
12 x0=df['排名']
13 y0=df['射正']
14 def func(x,c):
15 
16     k,a=c
17 
18     return k*x+a
19 
20 def errfc(c,x,y):
21 
22     return y-func(x,c)
23 
24 c0=(100,20)
25 
26 #调用拟合曲线
27 
28 print(opt.leastsq(errfc,c0,args=(x0,y0)))
29 
30 #s设置画布
31 
32 chinese=matplotlib.font_manager.FontProperties(fname='C:\Windows\Fonts\simsun.ttc')  
33 
34 plt.plot(x0,y0,"o",label=u"射正")
35 
36 plt.plot(x0,func(x0,opt.leastsq(errfc,c0,args=(x0,y0))[0]),label=u"拟合直线")
37 
38 plt.legend(loc=3,prop=chinese)
39 
40 plt.show()
41 
42 
43 
44 import matplotlib.pyplot as plt
45 
46 import matplotlib
47 
48 import numpy as np
49 
50 import scipy.optimize as opt
51 
52 import csv
53 
54 x0=df['点球']
55 y0=df['射门']
56 def func(x,c):
57 
58     k,a=c
59 
60     return k*x+a
61 
62 def errfc(c,x,y):
63 
64     return y-func(x,c)
65 
66 c0=(100,20)
67 
68 #调用拟合曲线
69 
70 print(opt.leastsq(errfc,c0,args=(x0,y0)))
71 
72 #s设置画布
73 
74 chinese=matplotlib.font_manager.FontProperties(fname='C:\Windows\Fonts\simsun.ttc')  
75 
76 plt.plot(x0,y0,"o",label=u"射门")
77 
78 plt.plot(x0,func(x0,opt.leastsq(errfc,c0,args=(x0,y0))[0]),label=u"拟合直线")
79 
80 plt.legend(loc=3,prop=chinese)
81 
82 plt.show()

 

 

 

 5.数据持久化

 1 #数据持久化
 2 import xlwt
 3 #设置数据的编码格式
 4 book = xlwt.Workbook(encoding='utf-8',style_compression=0)
 5 #建立一张sheet表
 6 sheet = book.add_sheet('单价',cell_overwrite_ok=True)
 7 #列名
 8 col = ['排名','名字','球队','次数','点球','时间','射门','射正']
 9 for i in range(0,8):
10         sheet.write(0,i,col[i])
11 #排名
12 m1=0
13 for i in a:
14             m1+=1
15             sheet.write(m1,0,a1[i])
16 #名字
17 m2=0
18 for i in c2.index:
19             m2+=1
20             sheet.write(m2,1,a2[i])
21 #球队
22 m3=0
23 for i in c3.index:
24             m3+=1
25             sheet.write(m3,2,a3[i])
26 #次数
27 m4=0
28 for i in c4.index:
29             m4+=1
30             sheet.write(m4,3,a4[i])
31 #点球
32 m5=0
33 for i in c5.index:
34             m5+=1
35             sheet.write(m5,4,a5[i])
36 #时间
37 m6=0
38 for i in c6.index:
39             m6+=1
40             sheet.write(m6,5,a6[i])
41 #射门
42 m7=0
43 for i in c7.index:
44             m7+=1
45             sheet.write(m7,6,a7[i])
46 #射正
47 k=0
48 for i in c.index:
49             k+=1
50             sheet.write(k,7,a[i])
51 #保存exls文件
52 savepath = 'E:\爬虫\足球数据.csv'
53 book.save(savepath)

 

   在上述代码中包括了数据的持久化,将所爬取的数据包括提取分析的数据进行保存到本地磁盘为xlsx文件的处理。

6.附完整程序代码

  1 #网易足球欧洲杯数据分析,爬取网页内容
  2 #获取信息
  3 import requests
  4 from bs4 import BeautifulSoup
  5 import json
  6 import pandas as pd
  7 #搜寻网页
  8 r=requests.get('http://api.sports.163.com/base/cs/union/player?cid=45&type=1')
  9 r.encoding="utf-8"
 10 data=json.loads(r.text)
 11 a=data['data']
 12 #遍历网页中的数据
 13 for i in a:
 14     print(i)
 15 #输出数据
 16 #创建一个序列空列表
 17 b=[]
 18 for i in range(1,51):
 19     b.append(i)
 20 print(b)
 21 #创建各个数据的空表
 22 a=data['data']
 23 attPenGoal=[]#点球
 24 goals=[]#进球
 25 names=[]#名字
 26 team=[]#球队
 27 ontargetScoringAtt=[]#射正
 28 minsPlayed=[]#出场时间
 29 games=[]#次数
 30 totalScoringAtt=[]#射门
 31 playerId=[]#队员编号
 32 teamId=[]#球队编号
 33 #每个数据都遍历循环
 34 for i in a:
 35     attPenGoal.append(i['attPenGoal'])
 36     goals.append(i['goals'])
 37     names.append(i['player'])
 38     games.append(i['games'])
 39     totalScoringAtt.append(i['totalScoringAtt'])
 40     team.append(i['team'])
 41     ontargetScoringAtt.append(i['ontargetScoringAtt'])
 42     minsPlayed.append(i['minsPlayed'])
 43     playerId.append(i['playerId'])
 44     teamId.append(i['teamId'])
 45 #导出各项数据
 46 df=pd.DataFrame({
 47                  '排名':b,
 48                  '名字':names, 
 49                  '球队':team,
 50                  '次数':games,
 51                  '点球':goals,
 52                  '射门':totalScoringAtt,
 53                  '射正':ontargetScoringAtt,
 54                  '出场时间':minsPlayed,
 55                  '队员编号':playerId,
 56                  '球队编号':teamId
 57                 })
 58 #存入足球数据的txt文本中
 59 df.to_csv('E:\爬虫\足球数据.txt',index=False)
 60 #插入下列数据
 61 df['射正']=ontargetScoringAtt
 62 df['出场时间']=minsPlayed
 63 df['队员编号']=playerId
 64 df['球队编号']=teamId
 65 #将文本数据变为csv表格数据
 66 df.to_csv('E:\爬虫\足球数据.csv',index=False)
 67 
 68 #插入排名数据
 69 df['排名']=b
 70 df.to_csv('E:\爬虫\足球数据.csv',index=True)
 71 #检查并显示重复值
 72 print(df.duplicated())
 73 #检查是否有空值
 74 print(df['点球'].isnull().value_counts())
 75 #绘制柱状图
 76 import pandas as pd
 77 import numpy as np
 78 import matplotlib.pyplot as plt
 79 plt.rcParams['font.sans-serif']=['SimHei'] 
 80 #用来正常显示中文标签
 81 a = df.排名
 82 b = df.点球
 83 plt.bar(a,b, color='red')
 84 plt.xlabel("排名")
 85 #横坐标为排名
 86 plt.ylabel("点球")
 87 #纵坐标为点球
 88 plt.title('欧洲射手榜')
 89 plt.show()
 90 #绘制散点图
 91 import matplotlib.pyplot as plt
 92 plt.rcParams['font.sans-serif']=['SimHei'] #用于正常显示中文标签
 93 size=50
 94 #调整大小
 95 plt.xlabel("排名")
 96 plt.ylabel("点球")
 97 #横坐标为排名,纵坐标为点球
 98 plt.title('欧洲射手榜')
 99 #表头是“欧洲射手榜”
100 a = df.排名
101 b = df.点球
102 plt.scatter(a,b,size, color="g", marker='.')
103 plt.show
104 #绘制射正与排名堆叠图
105 import pandas as pd
106 import numpy as np
107 import matplotlib.pyplot as plt
108 plt.rcParams['font.sans-serif']=['SimHei']
109 plt.rcParams['axes.unicode_minus'] = False   # 用来正常显示负号
110 plt.stackplot(df.射正, df.排名, color=['b',])
111 plt.xlabel("射正")
112 plt.ylabel("排名")
113 plt.title('射正与排名堆叠图')
114 plt.show()
115 #绘制折线图
116 plt.rcParams['font.sans-serif']=['SimHei'] #用来正常显示中文标签
117 a = df.排名
118 b = df.射正
119 plt.plot(a,b, color='r')
120 plt.xlabel("排名")
121 plt.ylabel("射正")
122 plt.title('排名与射正数据折线图')
123 plt.show()
124 #绘制回归图
125 import seaborn as sns
126 plt.rcParams['font.sans-serif']=['SimHei'] #用来正常显示中文标签
127 a = df.排名
128 b = df.射正
129 sns.regplot(a,b,color='g')
130 plt.xlabel("排名")
131 plt.ylabel("射正")
132 plt.title('排名与射正数据回归图')
133 plt.show()
134 #绘画扇形饼状图
135 from collections import Counter
136 import matplotlib.pyplot as plt
137 import matplotlib as mpt
138 mpt.rcParams['font.family']='fangsong'
139 oses = {
140 '意大利':22.37,
141 '丹麦': 20.31,
142 '英格兰': 16.28,
143 '比利时': 10.73,
144 '西班牙': 12.25,
145 '其他':18.06
146 
147 }
148 names = oses.keys()
149 percents = oses.values()
150 patches,texts,autotexts = plt.pie(percents,labels=names,autopct="%.2f%%",explode=(0,0.05,0,0,0,0))
151 for text in texts+autotexts:
152     plt.setp(text,fontproperties=font)
153     text.set_fontsize(10)
154 for text in autotexts:
155     text.set_color("white")
156 #绘制线性回归、拟合曲线
157 import matplotlib.pyplot as plt
158 
159 import matplotlib
160 
161 import numpy as np
162 
163 import scipy.optimize as opt
164 
165 import csv
166 
167 x0=df['排名']
168 y0=df['射正']
169 def func(x,c):
170 
171     k,a=c
172 
173     return k*x+a
174 
175 def errfc(c,x,y):
176 
177     return y-func(x,c)
178 
179 c0=(100,20)
180 
181 #调用拟合曲线
182 
183 print(opt.leastsq(errfc,c0,args=(x0,y0)))
184 
185 #s设置画布
186 
187 chinese=matplotlib.font_manager.FontProperties(fname='C:\Windows\Fonts\simsun.ttc')  
188 
189 plt.plot(x0,y0,"o",label=u"射正")
190 
191 plt.plot(x0,func(x0,opt.leastsq(errfc,c0,args=(x0,y0))[0]),label=u"拟合直线")
192 
193 plt.legend(loc=3,prop=chinese)
194 
195 plt.show()
196 
197 
198 
199 import matplotlib.pyplot as plt
200 
201 import matplotlib
202 
203 import numpy as np
204 
205 import scipy.optimize as opt
206 
207 import csv
208 
209 x0=df['点球']
210 y0=df['射门']
211 def func(x,c):
212 
213     k,a=c
214 
215     return k*x+a
216 
217 def errfc(c,x,y):
218 
219     return y-func(x,c)
220 
221 c0=(100,20)
222 
223 #调用拟合曲线
224 
225 print(opt.leastsq(errfc,c0,args=(x0,y0)))
226 
227 #s设置画布
228 
229 chinese=matplotlib.font_manager.FontProperties(fname='C:\Windows\Fonts\simsun.ttc')  
230 
231 plt.plot(x0,y0,"o",label=u"射门")
232 
233 plt.plot(x0,func(x0,opt.leastsq(errfc,c0,args=(x0,y0))[0]),label=u"拟合直线")
234 
235 plt.legend(loc=3,prop=chinese)
236 
237 plt.show()
238 #数据持久化
239 import xlwt
240 #设置数据的编码格式
241 book = xlwt.Workbook(encoding='utf-8',style_compression=0)
242 #建立一张sheet表
243 sheet = book.add_sheet('单价',cell_overwrite_ok=True)
244 #列名
245 col = ['排名','名字','球队','次数','点球','时间','射门','射正']
246 for i in range(0,8):
247         sheet.write(0,i,col[i])
248 #排名
249 m1=0
250 for i in a:
251             m1+=1
252             sheet.write(m1,0,a1[i])
253 #名字
254 m2=0
255 for i in c2.index:
256             m2+=1
257             sheet.write(m2,1,a2[i])
258 #球队
259 m3=0
260 for i in c3.index:
261             m3+=1
262             sheet.write(m3,2,a3[i])
263 #次数
264 m4=0
265 for i in c4.index:
266             m4+=1
267             sheet.write(m4,3,a4[i])
268 #点球
269 m5=0
270 for i in c5.index:
271             m5+=1
272             sheet.write(m5,4,a5[i])
273 #时间
274 m6=0
275 for i in c6.index:
276             m6+=1
277             sheet.write(m6,5,a6[i])
278 #射门
279 m7=0
280 for i in c7.index:
281             m7+=1
282             sheet.write(m7,6,a7[i])
283 #射正
284 k=0
285 for i in c.index:
286             k+=1
287             sheet.write(k,7,a[i])
288 #保存exls文件
289 savepath = 'E:\爬虫\足球数据.csv'
290 book.save(savepath)

四、结论(10分)

1.经过对主题数据的分析与可视化,可以得到哪些结论?

 

(1)根据欧洲杯射手榜的直方图,可以看出分为了5个稳定的状态,排名越靠前的球员点球数位列最高,排名越往后的球员比上一个层次都会较低,说明排名靠前的球员对于进球的把控有把握。

(2)根据排名与射正数据的折线图,可以看出射正数一直处于增长中,并且呈正增长。随着排名的靠后射正的次数逐渐增大,说明排名靠前的球员对于射正的概率并不高。

(3)根据排名与射正数据回归图,可以看出随着排名的递减,射正数也逐渐降低,可以反映出排名靠后的球员对于拿到球以及射门的次数少或者说明排名靠后的球员对于射正的把控率较低。

(4)根据扇形饼状图可知,意大利队伍相比于其他队伍的得分都较高,前几名的排名依次为:意大利,丹麦,英格兰,西班牙,比利时以及其他队伍,说明前面的几个队伍可能对于在团队合作上的运营以及配合相对于其他队会好上甚微。

(5)根据线性回归图、拟合直线可知,对于射正来说,拟合直线逐渐递减,射正的数量随着排名的递增而递减;对于射门来说,拟合直线在逐渐增加,射门的数量随着排名的递增而递增。说明了对于排名靠前的球员球的掌控率会高一些。

2.对本次程序设计任务完成的情况做一个简单的小结。

在这次对百度热榜的分析的过程中,我从中学会了不少函数及用法。很多次都卡在一个点上,绞尽脑汁去想解决问题的办法,通过观看b站的视频,百度搜索等方法去找寻答案。这两个星期来也养成了耐心和独立思考的习惯,并且提高了我对Python的兴趣。在完成设计的过程中,本次程序设计任务的各个部分都已完成,先是用requests库获取到目标网页的内容,再用json库解决了动态网页标签内容的获取问题,因为是动态网页所以无法通过beautiful soup 4 库来实现对标签内容的提取;再将所爬取的目标数据存储到本地的excel文件,实现数据的持久化,可为未来使用和研究减少代码量的修改;再将完整的数据转换为DataFrame进行清洗,最后通过matplotlib、pandas、seaborn等库对研究对象绘图分析。从一个大框架再不断细分完成每一部分的内容,使自己在实现较大工程时有了更明确的思路,本次圆满完成课程序设计任务更是一种自我肯定。在完成设计的过程中,需要感谢一些掌握知识比较透彻的同学对我出现的问题的指正。在绘制分析图时课本里的例题分析讲解的也比较透彻,当然这些知识在课上也都很清楚地进行过讲解,在课后作业中也进行了多次练习。在设计中,存在很多的不足之处,但是,通过这次设计能让我更好地警醒自己的Python水平和理解的有限。同样,这些不足会给我更大的动力去探索Python。总而言之,这次的设计很大程度,很大意义上对我起到了巨大的帮助和督促。课下的空余时间依然要不断努力学习新的知识完善自己。

posted @ 2021-12-27 16:40  吴迈  阅读(101)  评论(0编辑  收藏  举报