爬虫+MySQL+flask+echarts数据可视化
不得了,竟然把洛克王国给爬了,还把精灵属性值给可视化了,这下子终于知道哪个精灵好了
最近在学习数据可视化知识,就拿了小时候玩的洛克王国练了练手,爬取每个精灵的各项属性数据,存入到数据库中,并用flask框架进行可视化出来。
1.首先分析一下整个页面,所有的精灵信息存储在一个ul标签中,并且每个精灵详细信息的url放在这个a标签里,所以第一步就是先提取每个精灵具体信息页面的url
def parse(self,soup):
for i in soup.find_all('ul', id="cwdz_list"):
newurls = re.findall('<a href="/luoke/luokechongwu/(.*?).html">', str(i))
return newurls
2.提取到每个精灵的详细url后,分析详细页面,这里每个精灵的各项基础属性值及最大属性值都放在了这个tbody里,然后我们通过bs4库和正则把我们需要的信息提取出来,这里代码写的比较臃肿,因为我水平还不够,嘿嘿
def NewRespon(self,url):
r1 = requests.get(url, headers=self.headers)
r1.encoding = 'gb2312'
soup = BeautifulSoup(r1.text, 'html.parser')
for i in soup.find_all('div', 'netab cf'):
list1 = []
for j in i.find_all('tbody'):
list1.append(list(j.children))
if len(list1) <= 1:
return
item = list1[1]
if len(item) <= 7:
return
info = re.findall('<td class="td1">([\u4e00-\u9fa5]+)</td>', str(item[3]))
infoName = re.findall('<td>([\u4e00-\u9fa5]+)</td>', str(item[5]))
if len(infoName) == 0:
return
infoAttrs = re.findall('<td>(\d+)</td>', str(item[5]))
infoMax = re.findall('<td>(\d+)</td>', str(item[7]))
if len(infoMax) == 0:
return
return infoName,infoAttrs,infoMax
3.到这里,我们已经基本完成了爬虫的部分,下面把获取来的数据用键值对的方式存储起来,并转换称json格式,这里搞一下每个精灵的存储结构,之后用json库中的dumps方法存储为json文件
itemData = {
'name': '',
'leixing': '',
'energy': {
'min': '',
'max': ''
},
'attack': {
'min': '',
'max': ''
},
'defense': {
'min': '',
'max': ''
},
'speed': {
'min': '',
'max': ''
},
'MagicAttack': {
'min': '',
'max': ''
},
'MagicDefense': {
'min': '',
'max': ''
},
'sum': {
'min': '',
'max': ''
},
}
4.这个时候,我们就把我们的json文件里的信息存入到数据库中,先用json库中load方法把json文件转换成键值对形式,然后连接数据库并存入
with open('./items.json', 'r',encoding='utf-8') as f:
a = json.load(f)
print('数据解析完成!')
mydb = pymysql.connect(
host="localhost",
user="root",
passwd="root",
database="xk" # 用这个表
)
mycursor = mydb.cursor()
print('数据库链接OK!')
mycursor.execute('create table GenieInfo (name VARCHAR(255), PRIMARY KEY(name),leixing VARCHAR(255),EnergyMin VARCHAR(255),EnergyMax VARCHAR(255),AttackMin VARCHAR(255),AttackMax VARCHAR(255),DefenseMin VARCHAR(255),DefenseMax VARCHAR(255),SpeedMin VARCHAR(255),SpeedMax VARCHAR(255),MagicAttackMin VARCHAR(255),MagicAttackMax VARCHAR(255),MagicDefenseMin VARCHAR(255),MagicDefenseMax VARCHAR(255),SumMin VARCHAR(255),SumMax VARCHAR(255));')
print('数据表建成功')
print('开始添加数据!')
for i in a:
sql = "INSERT INTO GenieInfo (name,leixing,EnergyMin,EnergyMax,AttackMin,AttackMax,DefenseMin,DefenseMax,SpeedMin,SpeedMax,MagicAttackMin,MagicAttackMax,MagicDefenseMin,MagicDefenseMax,SumMin,SumMax) VALUES (%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s)"
val = (i['name'],i['leixing'],i['energy']['min'],i['energy']['max'],i['attack']['min'],i['attack']['max'],i['defense']['min'],i['defense']['max'],i['speed']['min'],i['speed']['max'],i['MagicAttack']['min'],i['MagicAttack']['max'],i['MagicDefense']['min'],i['MagicDefense']['max'],i['sum']['min'],i['sum']['max'])
mycursor.execute(sql, val)
mydb.commit()
print('数据保存成功!')
5.这个时候,我们的信息已经都放好了,那现在就开始搭建一个flask框架,因为flask本身并不支持连接数据库,所以我们使用了Flask-SQLAlchemy这个扩展包,SQLALCHEMY_DATABASE_URI变量中获取数据库的位置,然后实例化对象,有个要注意的是,这里数据表中必须要有主键,不然会报错
app.config['SQLALCHEMY_DATABASE_URI']=\
'mysql://root:root@localhost/xk'
app.config['SQLALCHEMY_TRACK_MODIFICATIONS']=False
db = SQLAlchemy(app)
class gen(db.Model):
__tablename__ = 'genieinfo'
name = db.Column(db.String(64),primary_key=True)
leixing = db.Column(db.String(64))
EnergyMin = db.Column(db.String(64))
EnergyMax = db.Column(db.String(64))
AttackMin = db.Column(db.String(64))
AttackMax = db.Column(db.String(64))
DefenseMin = db.Column(db.String(64))
DefenseMax = db.Column(db.String(64))
SpeedMin = db.Column(db.String(64))
SpeedMax = db.Column(db.String(64))
MagicAttackMin = db.Column(db.String(64))
MagicAttackMax = db.Column(db.String(64))
MagicDefenseMin = db.Column(db.String(64))
MagicDefenseMax = db.Column(db.String(64))
SumMin = db.Column(db.String(64))
SumMax = db.Column(db.String(64))
6.连接上数据库之后,不着急继续往下做,我们先建一个echarts的前端可视化出来,我的设想是做两个页面,一个是每个精灵的各项数据对比,一个是两个精灵的基础数据和满值数据对比,图形上我选择了基本的雷达图和折线柱状图,建立一个echarts首要的是 一个dom容器 然后配置项,实例化,具体每种可以去echarts官网查看样例,非常全,嘿嘿 ,这个是我的可视化的配置项代码
<script>
(function() {
var MyChart = echarts.init(document.querySelector(".box"));
var option = {
title: {
text: '{{n1}}、{{n2}}的基础属性对比',
show: true
},
color:['green','red'],
tooltip: {
trigger: 'axis',
axisPointer: {
type: 'cross',
crossStyle: {
color: 'red',
width: 2
}
}
},
legend: {
},
grid: {
left: '15%',
right: '15%',
bottom: '10%',
top: '10%',
containLabel: true
},
xAxis: {
type: 'category',
boundaryGap: false,
data: ['血量','攻击','防御', '速度','魔攻','魔抗']
},
yAxis: {
type: 'value',
name: ''
},
series: [{
name: '{{n1}}',
type: 'line',
data: {{min1 | safe}},
label: {
show: true
},
emphasis: {
focus: 'series'
},
}, {
name: '{{n2}}',
type: 'line',
data: {{min2 | safe}},
label: {
show: true
},
emphasis: {
focus: 'series'
},
}]
};
MyChart.setOption(option);
})();
(function(){
var MyChart = echarts.init(document.querySelector(".box1"));
var option = {
title: {
text: '{{n1}}、{{n2}}的满属性对比',
show:true
},
legend: {
data: ['{{n1}}', '{{n2}}']
},
color:['green','red'],
radar: {
indicator: [
{ name: '血量', max: 500 },
{ name: '攻击', max: 500 },
{ name: '防御', max: 500 },
{ name: '速度', max: 500 },
{ name: '魔攻', max: 500 },
{ name: '魔抗', max: 500 }
]
},
series: [
{
name: '',
type: 'radar',
data: [
{
value: {{max1 | safe}},
name: '{{n1}}'
},
{
value: {{max2 | safe}},
name: '{{n2}}'
}
]
}
]
};
MyChart.setOption(option);
})();
</script>
7.我们把可视化的页面做好之后,就差最后一步,往里面填充数据,我直接把数据库里的信息往前端页面送就完事了,有一个要注意的是,数据库里的信息在传的时候,可能会有空格 这就会导致配置项中不能识别数据,解决办法在变量名后面加个safe {{ 变量名 | safe }}
@app.route('/<name>')
def search(name):
x = gen.query.filter(gen.name==name).first()
n1=x.name
min1=[x.EnergyMin,x.AttackMin,x.DefenseMin,x.SpeedMin,x.MagicAttackMin,x.MagicDefenseMin]
max1=[x.EnergyMax,x.AttackMax,x.DefenseMax,x.SpeedMax,x.MagicAttackMax,x.MagicDefenseMax]
return render_template('lineBar.html',n=n1,min1=min1,max1=max1)
@app.route('/<name>/<name1>')
def compare(name,name1):
x = gen.query.filter(gen.name == name).first()
n1 = x.name
max1 = [x.EnergyMax, x.AttackMax, x.DefenseMax, x.SpeedMax, x.MagicAttackMax, x.MagicDefenseMax]
min1 = [x.EnergyMin, x.AttackMin, x.DefenseMin, x.SpeedMin, x.MagicAttackMin, x.MagicDefenseMin]
y = gen.query.filter(gen.name == name1).first()
n2 = y.name
max2 = [y.EnergyMax, y.AttackMax, y.DefenseMax, y.SpeedMax, y.MagicAttackMax, y.MagicDefenseMax]
min2 = [y.EnergyMin, y.AttackMin, y.DefenseMin, y.SpeedMin, y.MagicAttackMin, y.MagicDefenseMin]
return render_template('pie.html',n1=n1,n2=n2,max1=max1,max2=max2,min1=min1,min2=min2)
8.完事具备,直接开始run,尝试了一下,非常ok,当传入一个精灵名称的时候就是这个精灵的各项属性各时期的对比,当传入两个精灵名字的时候就是两个精灵的各项属性对比,
9. 完美撒花

魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。
更多推荐
所有评论(0)