Python高级应用程序设计任务

Python高级应用程序设计任务要求

用Python实现一个面向主题的网络爬虫程序,并完成以下内容:
(注:每人一题,主题内容自选,所有设计内容与源代码需提交到博客园平台)

一、主题式网络爬虫设计方案
1.主题式网络爬虫名称

《Python爬虫之NBA球队数据的爬取及分析》

 

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

爬取内容:本次对于“NBA官网”网站爬取的内容是:排名,球队名,场均篮板,场数,失误,抢断,场均助攻来观察球队之间的差距到底在哪里,可通过后续绘制直方图、折线图等观察数据的变化情况。

 

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

  本次主题式网络爬虫不仅包括了对网站的爬取,也包括对所爬取数据的清洗及分析,对我们的个人能力是一次巨大的提升。本次要爬取的“国家统计局”网站的相关内容,进行网站爬取首要先了解该网站的页面结构,通过分析,该网站的表单属于后台js提交的方式,也就是所谓的动态网页,传统的对于静态网页是爬取方法是行不通的,再对页面进一步分析后,发现元素审查后可获取到后台表单提交的URL,通过该URL可进行后续的爬取工作。后续将所爬取到的内容以excel的形式保存到本地电脑上,以实现数据的持久化,再通过该excel进行数据的清洗及分析,提取所爬取的目标内容,绘制对应图形,得出相应结论。

  技术难点:对动态网站的数据获取的URL难发现、所要的爬取的数据分布在网页的不同深度。

 

二、主题页面的结构特征分析
1.主题页面的结构特征

  (

 

 

 

 

 

 

 三、网络爬虫程序设计

1.数据爬取与采集

 1 import requests
 2 from bs4 import BeautifulSoup
 3 import json
 4 r=requests.get('https://china.nba.cn/stats2/league/teamstats.json?conference=All&division=All&locale=zh_CN&season=2021&seasonType=2')
 5 r.encoding="utf-8"
 6 data=json.loads(r.text)
 7 print(data)
 8 b=data['payload']['teams']
 9 for i in b:
10     print(i)
11 name=[]
12 for i in b:
13     name.append(i['profile']['name'])
14 for i in b:
15     pointsPg.append(i['statAverage']['pointsPg'])
16 rebsPg=[]
17 for i in b:
18     rebsPg.append(i['statAverage']['rebsPg'])
19 games=[]
20 for i in b:
21     games.append(i['statAverage']['games'])
22 turnoversPg=[]
23 for i in b:
24     turnoversPg.append(i['statAverage']['turnoversPg'])
25 stealsPg=[]
26 for i in b:
27     stealsPg.append(i['statAverage']['stealsPg'])
28 assistsPg=[]
29 for i in b:
30     assistsPg.append(i['statAverage']['assistsPg'])
31 rank=[]
32 for i in range(1,31):
33     rank.append(i)
34 print(name)
35 print(pointsPg)
36 print(rebsPg)
37 print(games)
38 print(turnoversPg)
39 print(stealsPg)
40 print(assistsPg)
41 import pandas as pd
42 df=pd.DataFrame({'排名':rank,
43                '球队名':name,
44                '场均篮板':rebsPg,
45                '场数':games,
46                '失误':turnoversPg,
47                '抢断':stealsPg,
48                '场均助攻':assistsPg,            
49                 })
50 df
51 df.to_csv('D:\python\球队数据.csv',index=False)

 

 

 

 

 

 

 1 import matplotlib
 2 chinese=matplotlib.font_manager.FontProperties(fname='C:\Windows\Fonts\simsun.ttc')  
 3 import matplotlib as mpl
 4 mpl.rcParams['font.sans-serif'] = ["SimHei"]
 5 mpl.rcParams["axes.unicode_minus"] = False
 6 import matplotlib.pyplot as plt
 7 plt.figure(figsize=(10,6))
 8 x=rank[0:5]
 9 x1=name[0:5]
10 a=['a','b','c']
11 total_width,n=0.8,3
12 #设置间距
13 width=total_width/n
14 #在偏移间距位置绘制柱状图1
15 for i in range(len(x)):
16     x[i]-=width
17 plt.bar(x1,rebsPg[0:5],label='场均篮板',fc='teal')
18 #设置数字标签
19 for a,b in zip(x,rebsPg[0:5]):
20     plt.text(a,b,b,ha='center',va='bottom',fontsize=10)
21 #在偏移间距位置绘制柱状图2
22 for i in range(len(x)):
23     x[i]+=width
24     plt.bar(x,turnoversPg[0:5],label='失误',tick_label=name,fc='darkorange')
25 for a,b in zip(x1,turnoversPg[0:5]):
26     plt.text(a,b,b,ha='center',va='bottom',fontsize=10)
27 #在偏移间距位置绘制柱状图3
28 for i in range(len(x)):
29     x[i]+=width
30 plt.bar(x,assistsPg[0:5],label='场均助攻',fc='lightcoral')
31 for a,b in zip (x1,assistsPg[0:5]):
32     plt.text(a,b,b,ha='center',va='bottom',fontsize=10)
1 import seaborn as sns
2 sns.regplot(df['排名'],df['场均篮板'])

 

 

1 data=pd.Series(games[0:8],name[0:8])
2 data.plot(kind='bar',title='场数')
3 plt.show()

 

 

 1 import matplotlib.pyplot as plt
 2 plt.rcParams['font.sans-serif']='SimHei'#设置中文显示
 3 plt.figure(figsize=(6,6))#将画布设定为正方形,则绘制的饼图是正圆
 4 label=name[0:5]#定义饼图的标签,标签是列表
 5 explode=[0.01,0.01,0.01,0.01,0.01]#设定各项距离圆心n个半径
 6 #plt.pie(values[-1,3:6],explode=explode,labels=label,autopct='%1.1f%%')#绘制饼图
 7 values=turnoversPg[0:5]
 8 plt.pie(values,explode=explode,labels=label,autopct='%1.1f%%')#绘制饼图
 9 plt.title('排名前5的失误比例')#绘制标题
10 plt.savefig('./')#保存图片
11 plt.show()

 

 

 1 #画出散点图
 2 plt.rcParams['font.sans-serif'] = ['SimHei']  # 用来正常显示中文标签
 3 plt.rcParams['axes.unicode_minus'] = False  # 用来正常显示负号
 4 N=10
 5 x=np.random.rand(N)
 6 y=np.random.rand(N)
 7 size=50
 8 plt.xlabel("排名")
 9 plt.ylabel("热度")
10 plt.scatter(x,y,size,color='r',alpha=0.5,marker="o")
11 #散点图  kind='reg'
12 sns.jointplot(x="排名",y="失误",data=df,kind='reg')
13 #  kind='hex'
14 sns.jointplot(x="排名",y="失误",data=df,kind='hex')
15 # kind='kde'
16 sns.jointplot(x="排名",y="失误",data=df,kind="kde",space=0,color='g')

 

 

 

 

 

 

1 data=pd.Series(stealsPg[0:8],name[0:8])
2 data.plot(kind='bar',title='抢断')
3 plt.show()

 

 

import matplotlib.pyplot as plt
plt.rcParams['font.sans-serif']='SimHei'#设置中文显示
plt.figure(figsize=(6,6))#将画布设定为正方形,则绘制的饼图是正圆
label=name[25:30]#定义饼图的标签,标签是列表
explode=[0.01,0.01,0.01,0.01,0.01]#设定各项距离圆心n个半径
#plt.pie(values[-1,3:6],explode=explode,labels=label,autopct='%1.1f%%')#绘制饼图
values=turnoversPg[25:30]
plt.pie(values,explode=explode,labels=label,autopct='%1.1f%%')#绘制饼图
plt.title('排名后5名的失误比例')#绘制标题
plt.savefig('./')#保存图片
plt.show()

 

 

 1 X = df.排名
 2 Y = df.场均篮板
 3 def A():
 4     plt.scatter(X,Y,color="blue",linewidth=2)
 5     plt.title("场均篮板的散点图",color="blue")
 6     plt.grid()
 7     plt.show()
 8 def B():
 9     plt.scatter(X,Y,color="green",linewidth=2)
10     plt.title("redu",color="blue")
11     plt.grid()
12     plt.show()
13 def func(p,x):
14     a,b,c=p
15     return a*x*x+b*x+c
16 def error(p,x,y):
17     return func(p,x)-y
18 def main():
19     plt.figure(figsize=(10,6))
20     p0=[0,0,0]
21     Para = leastsq(error,p0,args=(X,Y))
22     a,b,c=Para[0]
23     print("a=",a,"b=",b,"c=",c)
24     plt.scatter(X,Y,color="blue",linewidth=2)
25     x=np.linspace(0,20,20)
26     y=a*x*x+b*x+c
27     plt.plot(x,y,color="blue",linewidth=2,)
28     plt.title("场均篮板数分布")
29     plt.grid()
30     plt.show()
31 print(A())
32 print(B())
33 print(main())

 

 

 

 

 1 #绘制“场均助攻”的直方图
 2 import matplotlib.pyplot as plt
 3 import pandas as pd
 4 import numpy as np
 5 plt.rcParams['font.sans-serif'] = ['KaiTi'] # 指定默认字体
 6 plt.rcParams['axes.unicode_minus'] = False # 解决保存图像是负号'-'显示为方块的问题
 7 df['场均助攻'].plot(kind='bar',figsize=(15,10))
 8 plt.suptitle('场均助攻',fontsize=20)
 9 plt.xticks(fontsize=20)  #修改x轴字体大小为20
10 plt.yticks(fontsize=20)  #修改y轴字体大小为20
11 plt.xlabel('球队',fontsize=20)  #设置x轴标注为‘球队’,并调整字体大小
12 plt.ylabel('场均助攻',fontsize=20)  #设置y轴标注为‘国内生产总值(亿元)’,并调整字体大小
13 plt.show()

 

 

 1 X = df.排名
 2 Y = df.抢断
 3 def A():
 4     plt.scatter(X,Y,color="blue",linewidth=2)
 5     plt.title("场均抢断的散点图",color="blue")
 6     plt.grid()
 7     plt.show()
 8 def B():
 9     plt.scatter(X,Y,color="green",linewidth=2)
10     plt.title("redu",color="blue")
11     plt.grid()
12     plt.show()
13 def func(p,x):
14     a,b,c=p
15     return a*x*x+b*x+c
16 def error(p,x,y):
17     return func(p,x)-y
18 def main():
19     plt.figure(figsize=(10,6))
20     p0=[0,0,0]
21     Para = leastsq(error,p0,args=(X,Y))
22     a,b,c=Para[0]
23     print("a=",a,"b=",b,"c=",c)
24     plt.scatter(X,Y,color="blue",linewidth=2)
25     x=np.linspace(0,20,20)
26     y=a*x*x+b*x+c
27     plt.plot(x,y,color="blue",linewidth=2,)
28     plt.title("场均抢断分布")
29     plt.grid()
30     plt.show()
31 print(A())
32 print(B())
33 print(main())

 

 

 

 

 1 X = df.排名
 2 Y = df.失误
 3 def A():
 4     plt.scatter(X,Y,color="blue",linewidth=2)
 5     plt.title("场均失误的散点图",color="blue")
 6     plt.grid()
 7     plt.show()
 8 def B():
 9     plt.scatter(X,Y,color="green",linewidth=2)
10     plt.title("redu",color="blue")
11     plt.grid()
12     plt.show()
13 def func(p,x):
14     a,b,c=p
15     return a*x*x+b*x+c
16 def error(p,x,y):
17     return func(p,x)-y
18 def main():
19     plt.figure(figsize=(10,6))
20     p0=[0,0,0]
21     Para = leastsq(error,p0,args=(X,Y))
22     a,b,c=Para[0]
23     print("a=",a,"b=",b,"c=",c)
24     plt.scatter(X,Y,color="blue",linewidth=2)
25     x=np.linspace(0,20,20)
26     y=a*x*x+b*x+c
27     plt.plot(x,y,color="blue",linewidth=2,)
28     plt.title("场均失误分布")
29     plt.grid()
30     plt.show()
31 print(A())
32 print(B())
33 print(main())

 

 

 

 四、完整代码

  1 import requests
  2 from bs4 import BeautifulSoup
  3 import json
  4 r=requests.get('https://china.nba.cn/stats2/league/teamstats.json?conference=All&division=All&locale=zh_CN&season=2021&seasonType=2')
  5 r.encoding="utf-8"
  6 data=json.loads(r.text)
  7 print(data)
  8 b=data['payload']['teams']
  9 for i in b:
 10     print(i)
 11 name=[]
 12 for i in b:
 13     name.append(i['profile']['name'])
 14 for i in b:
 15     pointsPg.append(i['statAverage']['pointsPg'])
 16 rebsPg=[]
 17 for i in b:
 18     rebsPg.append(i['statAverage']['rebsPg'])
 19 games=[]
 20 for i in b:
 21     games.append(i['statAverage']['games'])
 22 turnoversPg=[]
 23 for i in b:
 24     turnoversPg.append(i['statAverage']['turnoversPg'])
 25 stealsPg=[]
 26 for i in b:
 27     stealsPg.append(i['statAverage']['stealsPg'])
 28 assistsPg=[]
 29 for i in b:
 30     assistsPg.append(i['statAverage']['assistsPg'])
 31 rank=[]
 32 for i in range(1,31):
 33     rank.append(i)
 34 print(name)
 35 print(pointsPg)
 36 print(rebsPg)
 37 print(games)
 38 print(turnoversPg)
 39 print(stealsPg)
 40 print(assistsPg)
 41 import pandas as pd
 42 df=pd.DataFrame({'排名':rank,
 43                '球队名':name,
 44                '场均篮板':rebsPg,
 45                '场数':games,
 46                '失误':turnoversPg,
 47                '抢断':stealsPg,
 48                '场均助攻':assistsPg,            
 49                 })
 50 df
 51 df.to_csv('D:\python\球队数据.csv',index=False)
 52 import matplotlib
 53 chinese=matplotlib.font_manager.FontProperties(fname='C:\Windows\Fonts\simsun.ttc')  
 54 import matplotlib as mpl
 55 mpl.rcParams['font.sans-serif'] = ["SimHei"]
 56 mpl.rcParams["axes.unicode_minus"] = False
 57 import matplotlib.pyplot as plt
 58 plt.figure(figsize=(10,6))
 59 x=rank[0:5]
 60 x1=name[0:5]
 61 a=['a','b','c']
 62 total_width,n=0.8,3
 63 #设置间距
 64 width=total_width/n
 65 #在偏移间距位置绘制柱状图1
 66 for i in range(len(x)):
 67     x[i]-=width
 68 plt.bar(x1,rebsPg[0:5],label='场均篮板',fc='teal')
 69 #设置数字标签
 70 for a,b in zip(x,rebsPg[0:5]):
 71     plt.text(a,b,b,ha='center',va='bottom',fontsize=10)
 72 #在偏移间距位置绘制柱状图2
 73 for i in range(len(x)):
 74     x[i]+=width
 75     plt.bar(x,turnoversPg[0:5],label='失误',tick_label=name,fc='darkorange')
 76 for a,b in zip(x1,turnoversPg[0:5]):
 77     plt.text(a,b,b,ha='center',va='bottom',fontsize=10)
 78 #在偏移间距位置绘制柱状图3
 79 for i in range(len(x)):
 80     x[i]+=width
 81 plt.bar(x,assistsPg[0:5],label='场均助攻',fc='lightcoral')
 82 for a,b in zip (x1,assistsPg[0:5]):
 83     plt.text(a,b,b,ha='center',va='bottom',fontsize=10)
 84 import seaborn as sns
 85 sns.regplot(df['排名'],df['场均篮板'])
 86 data=pd.Series(games[0:8],name[0:8])
 87 data.plot(kind='bar',title='场数')
 88 plt.show()
 89 import matplotlib.pyplot as plt
 90 plt.rcParams['font.sans-serif']='SimHei'#设置中文显示
 91 plt.figure(figsize=(6,6))#将画布设定为正方形,则绘制的饼图是正圆
 92 label=name[0:5]#定义饼图的标签,标签是列表
 93 explode=[0.01,0.01,0.01,0.01,0.01]#设定各项距离圆心n个半径
 94 #plt.pie(values[-1,3:6],explode=explode,labels=label,autopct='%1.1f%%')#绘制饼图
 95 values=turnoversPg[0:5]
 96 plt.pie(values,explode=explode,labels=label,autopct='%1.1f%%')#绘制饼图
 97 plt.title('排名前5的失误比例')#绘制标题
 98 plt.savefig('./')#保存图片
 99 plt.show()
100 #画出散点图
101 plt.rcParams['font.sans-serif'] = ['SimHei']  # 用来正常显示中文标签
102 plt.rcParams['axes.unicode_minus'] = False  # 用来正常显示负号
103 N=10
104 x=np.random.rand(N)
105 y=np.random.rand(N)
106 size=50
107 plt.xlabel("排名")
108 plt.ylabel("热度")
109 plt.scatter(x,y,size,color='r',alpha=0.5,marker="o")
110 #散点图  kind='reg'
111 sns.jointplot(x="排名",y="失误",data=df,kind='reg')
112 #  kind='hex'
113 sns.jointplot(x="排名",y="失误",data=df,kind='hex')
114 # kind='kde'
115 sns.jointplot(x="排名",y="失误",data=df,kind="kde",space=0,color='g')
116 data=pd.Series(stealsPg[0:8],name[0:8])
117 data.plot(kind='bar',title='抢断')
118 plt.show()
119 import matplotlib.pyplot as plt
120 plt.rcParams['font.sans-serif']='SimHei'#设置中文显示
121 plt.figure(figsize=(6,6))#将画布设定为正方形,则绘制的饼图是正圆
122 label=name[25:30]#定义饼图的标签,标签是列表
123 explode=[0.01,0.01,0.01,0.01,0.01]#设定各项距离圆心n个半径
124 #plt.pie(values[-1,3:6],explode=explode,labels=label,autopct='%1.1f%%')#绘制饼图
125 values=turnoversPg[25:30]
126 plt.pie(values,explode=explode,labels=label,autopct='%1.1f%%')#绘制饼图
127 plt.title('排名后5名的失误比例')#绘制标题
128 plt.savefig('./')#保存图片
129 plt.show()
130 X = df.排名
131 Y = df.场均篮板
132 def A():
133     plt.scatter(X,Y,color="blue",linewidth=2)
134     plt.title("场均篮板的散点图",color="blue")
135     plt.grid()
136     plt.show()
137 def B():
138     plt.scatter(X,Y,color="green",linewidth=2)
139     plt.title("redu",color="blue")
140     plt.grid()
141     plt.show()
142 def func(p,x):
143     a,b,c=p
144     return a*x*x+b*x+c
145 def error(p,x,y):
146     return func(p,x)-y
147 def main():
148     plt.figure(figsize=(10,6))
149     p0=[0,0,0]
150     Para = leastsq(error,p0,args=(X,Y))
151     a,b,c=Para[0]
152     print("a=",a,"b=",b,"c=",c)
153     plt.scatter(X,Y,color="blue",linewidth=2)
154     x=np.linspace(0,20,20)
155     y=a*x*x+b*x+c
156     plt.plot(x,y,color="blue",linewidth=2,)
157     plt.title("场均篮板数分布")
158     plt.grid()
159     plt.show()
160 print(A())
161 print(B())
162 print(main())
163 #绘制“场均助攻”的直方图
164 import matplotlib.pyplot as plt
165 import pandas as pd
166 import numpy as np
167 plt.rcParams['font.sans-serif'] = ['KaiTi'] # 指定默认字体
168 plt.rcParams['axes.unicode_minus'] = False # 解决保存图像是负号'-'显示为方块的问题
169 df['场均助攻'].plot(kind='bar',figsize=(15,10))
170 plt.suptitle('场均助攻',fontsize=20)
171 plt.xticks(fontsize=20)  #修改x轴字体大小为20
172 plt.yticks(fontsize=20)  #修改y轴字体大小为20
173 plt.xlabel('球队',fontsize=20)  #设置x轴标注为‘球队’,并调整字体大小
174 plt.ylabel('场均助攻',fontsize=20)  #设置y轴标注为‘国内生产总值(亿元)’,并调整字体大小
175 plt.show()
176 X = df.排名
177 Y = df.抢断
178 def A():
179     plt.scatter(X,Y,color="blue",linewidth=2)
180     plt.title("场均抢断的散点图",color="blue")
181     plt.grid()
182     plt.show()
183 def B():
184     plt.scatter(X,Y,color="green",linewidth=2)
185     plt.title("redu",color="blue")
186     plt.grid()
187     plt.show()
188 def func(p,x):
189     a,b,c=p
190     return a*x*x+b*x+c
191 def error(p,x,y):
192     return func(p,x)-y
193 def main():
194     plt.figure(figsize=(10,6))
195     p0=[0,0,0]
196     Para = leastsq(error,p0,args=(X,Y))
197     a,b,c=Para[0]
198     print("a=",a,"b=",b,"c=",c)
199     plt.scatter(X,Y,color="blue",linewidth=2)
200     x=np.linspace(0,20,20)
201     y=a*x*x+b*x+c
202     plt.plot(x,y,color="blue",linewidth=2,)
203     plt.title("场均抢断分布")
204     plt.grid()
205     plt.show()
206 print(A())
207 print(B())
208 print(main())
209 X = df.排名
210 Y = df.失误
211 def A():
212     plt.scatter(X,Y,color="blue",linewidth=2)
213     plt.title("场均失误的散点图",color="blue")
214     plt.grid()
215     plt.show()
216 def B():
217     plt.scatter(X,Y,color="green",linewidth=2)
218     plt.title("redu",color="blue")
219     plt.grid()
220     plt.show()
221 def func(p,x):
222     a,b,c=p
223     return a*x*x+b*x+c
224 def error(p,x,y):
225     return func(p,x)-y
226 def main():
227     plt.figure(figsize=(10,6))
228     p0=[0,0,0]
229     Para = leastsq(error,p0,args=(X,Y))
230     a,b,c=Para[0]
231     print("a=",a,"b=",b,"c=",c)
232     plt.scatter(X,Y,color="blue",linewidth=2)
233     x=np.linspace(0,20,20)
234     y=a*x*x+b*x+c
235     plt.plot(x,y,color="blue",linewidth=2,)
236     plt.title("场均失误分布")
237     plt.grid()
238     plt.show()
239 print(A())
240 print(B())
241 print(main())

五、总结

1.经过对数据的分析和可视化,从回归方程和拟合曲线可以看出散点大部分都落在曲线上。

2.越靠前的球队篮板数和场均助攻越多。

3.各个球队的场均失误数差不多,说明场均失误对球队实力差距影响不大。

小结:在这次对NBA球队的分析的过程中,我从中学会了不少函数及用法。很多次都卡在一个点上,绞尽脑汁去想解决问题的办法,通过观看b站的视频,百度搜索等方法去找寻答案。这两个星期来也养成了耐心和独立思考的习惯,并且提高了我对Python的兴趣。

posted @ 2021-12-28 21:36  正常点  阅读(39)  评论(0编辑  收藏  举报