✅ 操作成功!

英雄联盟亚运会

发布时间:2023-06-08 作者:admin 来源:文学

英雄联盟亚运会

英雄联盟亚运会

-

2023年2月21日发(作者:)

Python爬取OPGG⾥英雄联盟位置排名数据,及其可视化

⼀、选题背景

近年来电⼦竞技在当今社会越来越来受欢迎,同时电⼦竞技也成了亚运会项⽬之⼀。英雄联盟便是奥运会上的项⽬类型之⼀,我国便曾在亚运会的

英雄联盟项⽬上拿下冠军。所以我便选择了,英雄联盟这个项⽬来作为我的设计⽬标。

⼆、主题式⽹络爬⾍设计⽅案

1.主题式⽹络爬⾍名称

OPGG⾥英雄联盟位置排名数据,及其可视化

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

爬取opgg中上单及射⼿的排名,名字,胜率,出场率,并对其进⾏分析。

3.主题式⽹络爬⾍设计⽅案概述

(1)实现思路

先对⽬标页⾯进⾏分析,利⽤urllib.爬⾍库和BeautifulSoup库进⾏爬取解析,后分别⽤BeautifulSoup和正则表达式,分别查找所需要的数据。

然后再保存为.csv⽂件,最后进⾏可视化分析。

(2)技术难点

request库出现问题,被迫学习使⽤t库,在编写re库的正则表达式中,发现⾃⼰熟练程度低,出错较多,在数据可视化上也出现了

忘记代码的问题。

三、主题页⾯的结构特征分析

1.主题页⾯的结构与特征分析

⾸先是本机的usr-agent查询,做准备

由⽹站界⾯可以看出,右侧有英雄的详细信息,以Garen为例,胜率为53.84%,选取率为16.99%,常⽤位置为上单。

页⾯解析

现对⽹页源代码进⾏分析

代码中共有5个tbody标签(tbody标签开头结尾均有”tbody”,故共有10个”tbody”),对字段内容分析,分别为上单、打野、中单、ADC、辅助信

息。

再对tbody标签进⾏查找

由此代码可看出,英雄名、胜率及选取率都在td标签中,⽽每⼀个英雄信息在⼀个tr标签中,td⽗标签为tr标签,tr⽗标签为tbody标签

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

计划将Beautifulsoup查找,re库.正则表达式搭配查找

四、⽹络爬⾍程序设计

1.数据爬取与采集

1defaskurl(urlbase):

t引⽤t库

3#模拟浏览器头部信息,向⽹站发送信息

4header={

5\"User-Agent\":\"Mozilla/5.0(WindowsNT10.0;Win64;x64)AppleWebKit/537.36(KHTML,likeGecko)Chrome/96.0.4664.110Safari/537.36Edg/96.0.1054.62\"

6}

7#模拟⽤户代理

8request=t(urlbase,headers=header)

9#异常超时处理

10try:

11#html=\"\"

12response=n(request,timeout=5)

13html=().decode(\"utf-8\")

14#print(html)

15exceptExceptionasa:

16print(a)

17returnhtml

2.数据解析与整理

(1)采⽤BeautifulSoup解析提取数据

1importpandasaspd#导⼊pandas库

2importbs4#导⼊bs4库

3frombs4importBeautifulSoup#导⼊BeautifulSoup库

4url=\"/champion/statistics\"

5#获得html⽂档信息

6html=askurl(url)

7#解析数据

8soup=BeautifulSoup(html,\"\")

9top=[]

10name=[]#建⽴空列表⽤于储存数据

11winRate=[]

12pickRate=[]

13#遍历上单tbody标签的⼉⼦标签

(name=\"tbody\",attrs=\"tabItemchampion-trend-tier-TOP\").children:

15#判断tr是否为标签类型,去除空⾏

16ifisinstance(tr,):

17#查找tr标签下的td标签

18tds=tr(\'td\')

19#排名

(tds[0].string)

21#英雄名

(tds[3].find(attrs=\"champion-index-table__name\").string)

23#胜率%百分号对后续有影响,去除

(tds[4].e(\'%\',\'\'))

25#选取率

(tds[5].e(\'%\',\'\'))

27

28#将准确获得的数据保存到列表中

29df1=ame(data=[top,name,winRate,pickRate],index=[\'排名\',\'英雄名\',\'英雄胜率\',\'英雄出场率\'])

30#对⽂本进⾏,⾏换列,列换⾏

31df2=ame(.T,columns=)

32#保存数据到xlsx⽂件中

_excel(\'上单\')

(2)利⽤正则提取法提取数据

1frombs4importBeautifulSoup

2importre

3importpandasaspd

4ADtop=[]

5ADname=[]#设⽴空表格

6ADwinrate=[]

7ADpickrate=[]

8url=\"/champion/statistics\"

9#获得html⽂档信息

10html=askurl(url)

11#解析数据

12soup=BeautifulSoup(html,\"\")

13#取得射⼿标签内容

14ADCdata=_all(\"tbody\",class_=\"tabItemchampion-trend-tier-ADC\")

15#将BeautifulSoup类型转换为字符串类型,以便使⽤re库下的正则搜索

16strADCdata=str(ADCdata)

17#通过⽹页源码得知,需要收集的排名,英雄名信息为23条

18foriinrange(0,23):

19#排名设定约束

20findTop=e(r\'(d*?)\')

21#运⽤约束查找

(l(findTop,strADCdata)[i])

23#英雄名字设定约束

24findName=e(r\'(.*?)\')

25#运⽤约束查找

(l(findName,strADCdata)[i])

27#运⽤正则表达式查找时发现胜率与选取率除了标签,内容完全相同,导致在上⾯的循环中会出现交叉获得的问题出现。

28foriinrange(0,46,2):

29#英雄胜率设定约束获得偶数的胜率

30findWin=e(

31r\'(d{0,3}.d{2})%\')

(l(findWin,strADCdata)[i])

33#英雄出场率设定约束获得奇数的出场率

34findappear=e(

35r\'(d{0,3}.d{2})%

(l(findappear,strADCdata)[i+1])

37

38#将数据保存到列表中

39df3=ame(data=[ADtop,ADname,ADwinrate,ADpickrate],index=[\'排名\',\'英雄名\',\'英雄胜率\',\'英雄出场率\'])

40#对⽂本进⾏,⾏换列,列换⾏

41df4=ame(.T,columns=)

42#保存数据到xlsx⽂件中

_excel(\'射⼿\')

3.对数据进⾏清洗和处理

TOPrank=ame(_excel(\'上单\'))

print(())

##⽆⽆效列

#检查是否有重复值

print(ated())

#检查是否有空值

print(TOPrank[\'排名\'].isnull().value_counts())

#异常值处理

print(be())

#发现“排名”字段的最⼤值为56⽽平均值为28,假设异常值为56

#print(e([56,top[\'排名\'].mean()]))

4.数据分析与可视化

1:运⽤pyecharts制作表格视图

1importpandasaspd

entsimportTable

simportComponentTitleOpts

4

5#分别导⼊上单数据

6df_top=_excel(\'上单\')

7TOPTop=df_top[\'排名\'].()

8TOPName=df_top[\'英雄名\'].()

9TOPWin=df_top[\'英雄胜率\'].()

10TOPpick=df_top[\'英雄出场率\'].()

11

12#绘制上单表格视图

13table2=Table()

14headers2=[\"排名\",\"英雄名\",\"英雄胜率\",\"英雄出场率\"]

15rows2=[

16

17]

18foriinrange(0,56):

(df_[i].()[1:])#转换插⼊格式

(headers2,rows2)#插⼊数据

_global_opts(

22title_opts=ComponentTitleOpts(title=\"上单-强度排⾏\",subtitle=\"实时更新\")#设置标题与副标题

23)

(\"上单pyecharts表格.html\")

2:运⽤pyecharts制作柱状图

1importpandasaspd

importBar

simportThemeType

simportglobal_optionsasopts

5

6#分别导⼊上单数据

7df_top=_excel(\'上单\')

8TOPTop=df_top[\'排名\'].()

9TOPName=df_top[\'英雄名\'].()

10TOPWin=df_top[\'英雄胜率\'].()

11TOPpick=df_top[\'英雄出场率\'].()

12

13#绘制上单柱状图

14c=(

15Bar({\"theme\":NS})

_xaxis(TOPName)#设置x轴

_yaxis(\"英雄胜率\",TOPWin)#添加柱状体

_yaxis(\"英雄出场率\",TOPpick)

_global_opts(

20title_opts={\"text\":\"上单强度-⽰意图\",\"subtext\":\"综合胜率与出场率\"},#设置标题与副标题

21datazoom_opts=omOpts(),#分段

22xaxis_opts=ts(name_rotate=60,name=\"英雄名\",axislabel_opts={\"rotate\":35})#字体倾斜⾓度

23

24)

(\"上单强度柱状图.html\")

26)

3:运⽤pyecharts制作折线图

1importpandasaspd

sasopts

importLine

4#分别导⼊上单数据

5df_top=_excel(\'上单\')

6TOPTop=df_top[\'排名\'].()

7TOPName=df_top[\'英雄名\'].()

8TOPWin=df_top[\'英雄胜率\'].()

9TOPpick=df_top[\'英雄出场率\'].()

10(

11Line()

_global_opts(

13tooltip_opts=pOpts(is_show=False),

14xaxis_opts=ts(type_=\"category\"),

15yaxis_opts=ts(

16type_=\"value\",

17axistick_opts=ckOpts(is_show=True),

18splitline_opts=ineOpts(is_show=True),

19),

20)

_xaxis(xaxis_data=TOPName)

_yaxis(

23series_name=\"\",

24y_axis=TOPWin,

25symbol=\"emptyCircle\",

26is_symbol_show=True,

27label_opts=pts(is_show=False),

28)

_global_opts(

30title_opts={\"text\":\"上单英雄-对应胜率曲线\",\"subtext\":\"强度曲线\"},

31datazoom_opts=omOpts(),#分段

32xaxis_opts=ts(name_rotate=60,name=\"英雄名\",axislabel_opts={\"rotate\":35})#字体倾斜⾓度

33)

(\"上单胜率折线图.html\")

35)

5.完整代码

1#-*-coding=utf-8-*-

2#@Time:2021/12/2414:49

3#@Author:真建彬

4#@StudentNumber:2003010221

5#@File:

6

7defaskurl(urlbase):

t

9#模拟浏览器头部信息,向⽹站发送信息

10header={

11\"User-Agent\":\"Mozilla/5.0(WindowsNT10.0;Win64;x64)AppleWebKit/537.36(KHTML,likeGecko)Chrome/96.0.4664.110Safari/537.36Edg/96.0.1054.62\"

12}

13#模拟⽤户代理

14request=t(urlbase,headers=header)

15#异常超时处理

16try:

17#html=\"\"

18response=n(request,timeout=5)

19html=().decode(\"utf-8\")

20#print(html)

21exceptExceptionasa:

22print(a)

23returnhtml

24

25defmain():

importBar

simportThemeType

28importre

29importpandasaspd

30importbs4#导⼊bs4库

31frombs4importBeautifulSoup#导⼊BeautifulSoup库

sasopts

importLine

entsimportTable

simportComponentTitleOpts

36url=\"/champion/statistics\"

37#获得html⽂档信息

38html=askurl(url)

39#解析数据

40soup=BeautifulSoup(html,\"\")

41top=[]

42name=[]#建⽴空列表⽤于储存数据

43winRate=[]

44pickRate=[]

45#遍历上单tbody标签的⼉⼦标签

(name=\"tbody\",attrs=\"tabItemchampion-trend-tier-TOP\").children:

47#判断tr是否为标签类型,去除空⾏

48ifisinstance(tr,):

49#查找tr标签下的td标签

50tds=tr(\'td\')

51#排名

(tds[0].string)

53#英雄名

(tds[3].find(attrs=\"champion-index-table__name\").string)

55#胜率%百分号对后续有影响,去除

(tds[4].e(\'%\',\'\'))

57#选取率

(tds[5].e(\'%\',\'\'))

59

60#将准确获得的数据保存到列表中

61df1=ame(data=[top,name,winRate,pickRate],index=[\'排名\',\'英雄名\',\'英雄胜率\',\'英雄出场率\'])

62#对⽂本进⾏,⾏换列,列换⾏

63df2=ame(.T,columns=)

64#保存数据到xlsx⽂件中

_excel(\'上单\')

66##读取⽂件

67TOPrank=ame(_excel(\'上单\'))

68print(())

69

70##⽆⽆效列

71

72#检查是否有重复值

73print(ated())

74

75#检查是否有空值

76print(TOPrank[\'排名\'].isnull().value_counts())

77

78#异常值处理

79print(be())

80#发现“排名”字段的最⼤值为56⽽平均值为28,假设异常值为56

81#print(e([56,top[\'排名\'].mean()]))

82

83

84

85ADtop=[]

86ADname=[]#设⽴空表格

87ADwinrate=[]

88ADpickrate=[]

89#取得射⼿标签内容

90ADCdata=_all(\"tbody\",class_=\"tabItemchampion-trend-tier-ADC\")

91#将BeautifulSoup类型转换为字符串类型,以便使⽤re库下的正则搜索

92strADCdata=str(ADCdata)

93#通过⽹页源码得知,需要收集的排名,英雄名信息为23条

94foriinrange(0,23):

95#排名设定约束

96findTop=e(r\'(d*?)\')

97#运⽤约束查找

(l(findTop,strADCdata)[i])

99#英雄名字设定约束

100findName=e(r\'(.*?)\')

101#运⽤约束查找

(l(findName,strADCdata)[i])

103#运⽤正则表达式查找时发现胜率与选取率除了标签,内容完全相同,导致在上⾯的循环中会出现交叉获得的问题出现。

104foriinrange(0,46,2):

105#英雄胜率设定约束获得偶数的胜率

106findWin=e(r\'(d{0,3}.d{2})%\')

(l(findWin,strADCdata)[i])

108#英雄出场率设定约束获得奇数的出场率

109findappear=e(r\'(d{0,3}.d{2})%

(l(findappear,strADCdata)[i+1])

111

112#将数据保存到列表中

113df3=ame(data=[ADtop,ADname,ADwinrate,ADpickrate],index=[\'排名\',\'英雄名\',\'英雄胜率\',\'英雄出场率\'])

114#对⽂本进⾏,⾏换列,列换⾏

115df4=ame(.T,columns=)

116#保存数据到xlsx⽂件中

_excel(\'射⼿\')

118

119ADCrank=ame(_excel(\'射⼿\'))

120print(())

121

122##⽆⽆效列

123

124#检查是否有重复值

125print(ated())

126

127#检查是否有空值

128print(ADCrank[\'排名\'].isnull().value_counts())

129

130#异常值处理

131print(be())

132#发现“排名”字段的最⼤值为23⽽平均值为12,假设异常值为23

133#print(e([23,top2[\'排名\'].mean()]))

134

135#数据可视化:

136

137

138#分别导⼊射⼿数据

139df_ADC=_excel(\'射⼿\')

140ADCTop=df_ADC[\'排名\'].()

141ADCName=df_ADC[\'英雄名\'].()

142ADCWin=df_ADC[\'英雄胜率\'].()

143ADCpick=df_ADC[\'英雄出场率\'].()

144

145#分别导⼊上单数据

146df_top=_excel(\'上单\')

147TOPTop=df_top[\'排名\'].()

148TOPName=df_top[\'英雄名\'].()

149TOPWin=df_top[\'英雄胜率\'].()

150TOPpick=df_top[\'英雄出场率\'].()

151

152#利⽤pyecharts做表格视图

153

154#绘制射⼿表格视图

155table1=Table()

156headers1=[\"排名\",\"英雄名\",\"英雄胜率\",\"英雄出场率\"]#设置表头

157rows1=[

158

159]

160foriinrange(0,23):

(df_[i].()[1:])#转换插⼊格式

(headers1,rows1)#插⼊数据

_global_opts(

164title_opts=ComponentTitleOpts(title=\"射⼿-强度排⾏\",subtitle=\"实时更新\")#设置标题与副标题

165)

(\"射⼿pyecharts表格.html\")

167

168

169#绘制上单表格视图

170table2=Table()

171headers2=[\"排名\",\"英雄名\",\"英雄胜率\",\"英雄出场率\"]

172rows2=[

173

174]

175foriinrange(0,56):

(df_[i].()[1:])#转换插⼊格式

(headers2,rows2)#插⼊数据

_global_opts(

179title_opts=ComponentTitleOpts(title=\"上单-强度排⾏\",subtitle=\"实时更新\")#设置标题与副标题

180)

(\"上单pyecharts表格.html\")#记录

182

183#利⽤pyecharts绘制柱状图

184

185#绘制射⼿柱状图

186c=(

187Bar({\"theme\":NS})

_xaxis(ADCName)#设置x轴

_yaxis(\"英雄胜率\",ADCWin)#添加柱状体

_yaxis(\"英雄出场率\",ADCpick)

_global_opts(

192title_opts={\"text\":\"射⼿强度-⽰意图\",\"subtext\":\"综合胜率与出场率\"},#设置标题与副标题

193datazoom_opts=omOpts(),#分段

194xaxis_opts=ts(name_rotate=60,name=\"英雄名\",axislabel_opts={\"rotate\":35})#字体倾斜⾓度

195

196)

(\"ADC强度柱状图.html\")

198)

199#绘制上单柱状图

200c=(

201Bar({\"theme\":NS})

_xaxis(TOPName)#设置x轴

_yaxis(\"英雄胜率\",TOPWin)#添加柱状体

_yaxis(\"英雄出场率\",TOPpick)

_global_opts(

206title_opts={\"text\":\"上单强度-⽰意图\",\"subtext\":\"综合胜率与出场率\"},#设置标题与副标题

207datazoom_opts=omOpts(),#分段

208xaxis_opts=ts(name_rotate=60,name=\"英雄名\",axislabel_opts={\"rotate\":35})#字体倾斜⾓度

209

210)

(\"上单强度柱状图.html\")

212)

213

214

215#利⽤pyecharts绘制折线图:

216

217#绘制射⼿折线图

218(

219Line()

_global_opts(

221tooltip_opts=pOpts(is_show=False),

222xaxis_opts=ts(type_=\"category\"),

223yaxis_opts=ts(

224type_=\"value\",

225axistick_opts=ckOpts(is_show=True),

226splitline_opts=ineOpts(is_show=True),

227),

228)

_xaxis(xaxis_data=ADCName)

_yaxis(

231series_name=\"\",

232y_axis=ADCWin,

233symbol=\"emptyCircle\",

234is_symbol_show=True,

235label_opts=pts(is_show=False),

236)

_global_opts(

238title_opts={\"text\":\"射⼿英雄-对应胜率曲线\",\"subtext\":\"强度曲线\"},

239datazoom_opts=omOpts(),#分段

240xaxis_opts=ts(name_rotate=60,name=\"英雄名\",axislabel_opts={\"rotate\":35})#字体倾斜⾓度

241

242)

(\"ADC胜率折线图.html\")

244)

245

246#绘制上单折线图

247(

248Line()

_global_opts(

250tooltip_opts=pOpts(is_show=False),

251xaxis_opts=ts(type_=\"category\"),

252yaxis_opts=ts(

253type_=\"value\",

254axistick_opts=ckOpts(is_show=True),

255splitline_opts=ineOpts(is_show=True),

256),

257)

_xaxis(xaxis_data=TOPName)

_yaxis(

260series_name=\"\",

261y_axis=TOPWin,

262symbol=\"emptyCircle\",

263is_symbol_show=True,

264label_opts=pts(is_show=False),

265)

_global_opts(

267title_opts={\"text\":\"上单英雄-对应胜率曲线\",\"subtext\":\"强度曲线\"},

268datazoom_opts=omOpts(),#分段

269xaxis_opts=ts(name_rotate=60,name=\"英雄名\",axislabel_opts={\"rotate\":35})#字体倾斜⾓度

270

271)

(\"上单胜率折线图.html\")

273)

274

275

276

277

278

279#调⽤主函数

280if__name__==\"__main__\":

281main()

282print(\'程序运⾏成功\')

五、总结

1.经过对主题数据的分析与可视化,可以得到哪些结论?是否达到预期的⽬标?

结论:

(1)游戏⾥英雄强度强,并不代表着⾼选取率⾼胜率的结果。

(2)获取和处理数据上我巩固了许多知识,使运⽤他们变得更加熟悉。

达到了预期的⽬标。

2.在完成此设计过程中,得到哪些收获?以及要改进的建议?

收获:熟练了爬⾍的操作,且能更好的运⽤正则表达式

建议:有很多⼩细节卡了我很久,还是需要稳固基础。

👁️ 阅读量:0