python数据可视化
Pandas数据分析从入门到实战,零基础小白保姆级Python数据分析教程
NumPy教程,保姆级基础入门Python数据分析
python数据可视化Matplotlib绘图教程,Matplotlib柱状图|Matplotlib动态图|Matplotlib散点图
1.Flask入门
1.1 了解Flask框架
Flask作为Web框架,它的作用主要是为了开发Web应用程序。那么我们首先来了解下Web应用程序。Web应用程序 (World Wide Web)诞生最初的目的,是为了利用互联网交流工作文档。
一切从客户端发起请求开始。
- ·所有Flask程序都必须创建一个程序实例。
- 当客户端想要获取资源时,一般会通过浏览器发起HTTP请求。
- 此时,Web服务器使用一种名为WEB服务器网关接口的WSGl(WebServerGatewayInterface)协议,把来自客户端的请求都交给Flask程序实例。
- Flask使用Werkzeug来做路由分发(URL请求和视图函数之间的对应关系)根据每个URL请求,找到具体的视图函数。
- 在Fask程序中,路由一般是通过程序实例的装饰器实现。通过调用视图函数,获取到数据后,把数据传入HTML模板文件中,模板引擎负责渲染HTTP响应数据,然后由Flask返回响应数据给浏览器,最后浏览器显示返回的结果。
1.2 为什么要用Web框架?
web网站发展至今,特别是服务器端,涉及到的知识、内容,非常广泛。这对程序员的要求会越来越高。如果采用成熟,稳健的框架,那么一些基础的工作,比如,网络操作、数据库访问、会话管理等都可以让框架来处理,那么程序开发人员可以把精力放在县体的业务逻辑上面。使用Web框架开发Web应用程序可以降低开发难度,提高开发效率。
总结一句话:避免重复造轮子
1.3 Flask框架的诞生
Flask诞生于2010年,是Armin ronacherython语言基于Werkzeug工具箱编写的轻量级Web开发框(人名)用架。它主要面向需求简单的小应用。
用到扩展(邮件扩展Flask-Mail,用户认证Flask-Login)Flask本身相当于一个内核,其他几乎所有的功能都要都需要用第三方的扩展来实现。比如可以用Flask-extension加入ORM、窗体验证工具,文件上传、身份验证等。Flask没有默认使用的数据库,你可以选择MySQL,也,可以用NoSQL。其 WSGI 工具箱采用 Werkzeug(路由模块),有模板引擎则使用Jinja2 。
可以说Flask框架的核心就是Werkzeug和Jinja2。Python最出名的框架要数Django,此外还有Flask、ornado等框架。虽然Flask不是最出名的框架,但是Flask应该算是最灵活的框架之一,这也是Flask受到广大开发者喜爱的原因。
Flask扩展包
- Flask-SQLalchemy:操作数据库;
- Flask-migrate:管理迁移数据库
- Flask-Mail:邮件
- Flask-WTF:表单
- Flask-script:插入脚本
- Flask-Login:认证用户状态
- Flask-RESTfuI:开发REST API的工具)
- Flask-Bootstrap:集成前端Twitter Bootstrap框架
- Flask-Moment:本地化日期和时间
1.4 Flask框架的使用
新建flask项目
项目生成后自带static 静态资源,templates 模板,app.py主程序
app.py文件作用
from flask import Flask #引入flask类
# 实例化一个app
app = Flask(__name__)
# 路由解析,通过用户访问的路径,匹配相应的函数
@app.route('/') #访问根目录http://127.0.0.1:5000/,就传递给hello_world()函数
def hello_world(): # 这里是应用的核心代码
return 'Hello World!'
if __name__ == '__main__':
app.run() # 调用app去监听5000端口 用户如果访问看路径是决定传递给那个函数
代码更新需要关闭项目
如果想要一边写代码一边看代码效果,要开启debug模式,可以这么开启
f __name__ == '__main__':
app.run(debug=True) # 调用app去监听5000端口 用户如果访问看路径是决定传递给那个函数
方法二:针对第一种方法没有成功开启debug的
需要修改配置文件
指定访问路径
我们在核心代码处新建一个函数,并指定一个路径用来访问该函数,实例化app和调用app.run在这个项目开放中是不需要改动的,只需要在中间新增代码就行
@app.route("/index")
def hello():
return "你好"
指定参数的传入
@app.route("/user/<name>") #模拟一个登录的过程 name是传递的参数
def welcome(name): #需要把路由中传递的值作为参数传递给函数的形参
return "你好 %s" % name #代码中就可以访问用户传递的变量了
传递不同类型的参数
@app.route("/user/<int:id>") # 指明传递的参数是int类型的id
def welcome(id): #需要把路由中传递的值作为参数传递给函数的形参
return "你好 %d" % id #代码中就可以访问用户传递的变量了
路由问题
路由路径不能重复,用户只能通过唯一路径访问特定的函数,函数的名字也不能重复,唯一的路径 唯一的函数
前端页面的处理
Werkzeug来做路由分发,jinja2用来前端页面
先导入渲染模板文件
from flask import Flask, render_template
再写核心代码
指定访问 /目录会返回render_template渲染的html前端页面
@app.route("/ind")
def index2():
return render_template("index.html")
返回的前端页面哪里来的呢,通过在主目录下的templates模板下新建html页面, render_template会加载指定页面
页面传递普通变量
欢迎光临是我们手动写的,怎么让我们的程序内容自动返回到页面上呢,其实使用函数中的变量再加上render_template在指定的页面把函数的变量传递过去,在hmtl页面使用{{ 变量名 }}来接受我们函数返回的内容
import datetime
@app.route("/")
def index3():
time = datetime.datetime.now()
time = time.strftime("%Y-%m-%d %H:%M:%S")
return render_template("index.html", time=time)
页面传递列表变量
import datetime
@app.route("/")
def index3():
time = datetime.datetime.now()
time = time.strftime("%Y-%m-%d %H:%M:%S")
name = ['张三','王五','李四']
return render_template("index.html", time=time,list=name)
前端页面应该怎么显示list列表呢,使用jinja2的固定格式
<br>
欢迎光临!今天是{{ time }}
<br/>
今天值班的有:<br>
{% for i in list %}
<li>{{ i }}</li>
{% endfor %}
页面传递字典变量
@app.route("/")
def index3():
time = datetime.datetime.now()
time = time.strftime("%Y-%m-%d %H:%M:%S")
name = ['张三','王五','李四']
task = {'任务':'打扫卫生','时间':'3小时'}
return render_template("index.html", time=time,list=name,task=task)
任务:
<table border="1">
{% for key,value in task.items() %} # <!--用大括号和百分号括起来的是控制结构,还有if--
<tr>
<td>{{ key }}</td>
<td>{{ value }}</td>
</tr>
{% endfor %}
</table>
页面表单提交
首先我们新建一个目录下面先写一个表单页面reg.html
<form action="http://localhost:5000/result" method="post">
<p>姓名:<input type="text" name="name"></p>
<p>年龄:<input type="text" name="age"></p>
<p>性别:<input type="text" name="sex"></p>
<p>地址:<input type="text" name="add"></p>
<p><input type="submit" value="提交"></p>
</form>
让主程序把html显示在页面上用户填写,注意路由和模板路径的不同
@app.route("/test/reg")
def reg():
return render_template("test/reg.html")
用户填写完呢,我们需要把用户提交的东西显示出来,先写主程序接受form提交的数据,接受使用request库
import request
@app.route("/result",methods=["POST","GET"])
def result():
if request.method == "POST":
result = request.form #接受整个form的数据返回字典
return render_template("test/result.html",result=result)
接受完我们需要渲染在result.html页面上,让用户看到他提交的结果
<table border="1">
{% for key,value in result.items() %} # <!--用大括号和百分号括起来的是控制结构,还有if--
<tr>
<td>{{ key }}</td>
<td>{{ value }}</td>
</tr>
{% endfor %}
</table>
如果提示方法不允许,在主程序中设置method
@app.route("/test/result",methods=["GET","POST"])
def result():
result = request.form # 接受整个form的数据返回字典
return render_template("test/result.html", result=result)
动态获取上传表单地址
反向路由 获取主程序中路由地址为result的完整路径
<form action="{{ url_for("result") }}" method="post">
<p>姓名:<input type="text" name="name"></p>
<p>年龄:<input type="text" name="age"></p>
<p>性别:<input type="text" name="sex"></p>
<p>地址:<input type="text" name="add"></p>
<p><input type="submit" value="提交"></p>
</form>
1.5 Flask项目实例
豆瓣TOP205项目数据可视化
html页面制作
由于html页面制作比较繁琐,和需要各种设计,所以这里我们直接使用网站模板来展示,直接修改网站html内容到达我们的需求即可
模板网站链接:
模板之家》》一站式建站平台》》》seo营销推广公司响应式网站模板:http://www.cssmoban.com/cssthemes/9296.shtml
模板文件放置
修改首页模板
涉及的html代码我已经上传本博客,可直接沿用修改,删除多余模块,修改文本内容,移植其他模块,也可自行修改设计更美观的页面
其他页面模板
其他页面的效果暂时设计成这样的统一模板后续慢慢修改
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta content="width=device-width, initial-scale=1.0" name="viewport">
<title>豆瓣电影TOP250数据分析</title>
<meta content="" name="descriptison">
<meta content="" name="keywords">
<!-- Favicons -->
<link href="static/assets/img/favicon.png" rel="icon">
<link href="static/assets/img/apple-touch-icon.png" rel="apple-touch-icon">
<!-- Google Fonts -->
<link href="https://fonts.googleapis.com/css?family=Open+Sans:300,300i,400,400i,600,600i,700,700i|Raleway:300,300i,400,400i,600,600i,700,700i,900" rel="stylesheet">
<!-- Vendor CSS Files -->
<link href="static/assets/vendor/bootstrap/css/bootstrap.min.css" rel="stylesheet">
<link href="static/assets/vendor/icofont/icofont.min.css" rel="stylesheet">
<link href="static/assets/vendor/boxicons/css/boxicons.min.css" rel="stylesheet">
<link href="static/assets/vendor/animate.css/animate.min.css" rel="stylesheet">
<link href="static/assets/vendor/venobox/venobox.css" rel="stylesheet">
<link href="static/assets/vendor/aos/aos.css" rel="stylesheet">
<!-- Template Main CSS File -->
<link href="static/assets/css/style.css" rel="stylesheet">
</head>
<body>
<!-- ======= Header ======= -->
<header id="header">
<div class="container">
<div class="logo float-left">
<h1 class="text-light"><a href="index.html"><span>Mamba</span></a></h1>
<!-- Uncomment below if you prefer to use an image logo -->
<!-- <a href="index.html"><img src="static/assets/img/logo.png" alt="" class="img-fluid"></a>-->
</div>
<nav class="nav-menu float-right d-none d-lg-block">
<ul>
<li class="active"><a href="/index">首页 <i class="la la-angle-down"></i></a></li>
<li><a href="/movie">电影</a></li>
<li><a href="/score">评分</a></li>
<li><a href="/word">词云</a></li>
<li><a href="/team">团队</a></li>
</ul>
</nav><!-- .nav-menu -->
</div>
</header><!-- End Header -->
<section id="team" class="team">
<div class="container">
<div class="section-title">
<h2>豆瓣电影TOP250数据分析</h2>
<p>应用Python爬虫,Flask框架,Echarts,WordCloud等技术实现</p>
</div>
<!-- ======= Counts Section ======= -->
<section class="counts section-bg">
<div class="container">
</div>
</section><!-- End Counts Section -->
</div>
</section><!-- End Our Team Section -->
<!-- ======= Footer ======= -->
<footer id="footer">
<div class="container">
<div class="copyright">
© Copyright <strong><span>Mamba</span></strong>. All Rights Reserved
</div>
<div class="credits">
More Templates <a href="http://www.cssmoban.com/" target="_blank" title="模板之家">模板之家</a> - Collect from <a href="http://www.cssmoban.com/" title="网页模板" target="_blank">网页模板</a>
</div>
</div>
</footer><!-- End Footer -->
<a href="#" class="back-to-top"><i class="icofont-simple-up"></i></a>
<!-- Vendor JS Files -->
<script src="static/assets/vendor/jquery/jquery.min.js"></script>
<script src="static/assets/vendor/bootstrap/js/bootstrap.bundle.min.js"></script>
<script src="static/assets/vendor/jquery.easing/jquery.easing.min.js"></script>
<script src="static/assets/vendor/php-email-form/validate.js"></script>
<script src="static/assets/vendor/jquery-sticky/jquery.sticky.js"></script>
<script src="static/assets/vendor/venobox/venobox.min.js"></script>
<script src="static/assets/vendor/waypoints/jquery.waypoints.min.js"></script>
<script src="static/assets/vendor/counterup/counterup.min.js"></script>
<script src="static/assets/vendor/isotope-layout/isotope.pkgd.min.js"></script>
<script src="static/assets/vendor/aos/aos.js"></script>
<!-- Template Main JS File -->
<script src="static/assets/js/main.js"></script>
<style>
.copyrights{text-indent:-9999px;height:0;line-height:0;font-size:0;overflow:hidden;}
</style>
<div class="copyrights" id="links20210126">
Collect from <a href="http://www.cssmoban.com/" title="网站模板">模板之家</a>
<a href="https://www.chazidian.com/" title="查字典">查字典</a>
</div>
</body>
</html>
设计路由访问链接
网站各功能点击会直接访问href设定的路由,我们只需要在主程序中设置访问那个路由返回那个页面即可
<li><a href="/index">首页
<li><a href="/movie">电影</a></li>
<li><a href="/score">评分</a></li>
<li><a href="/word">词云</a></li>
<li><a href="/team">团队</a></li>
编写程序路由返回
from flask import Flask,render_template,request
import sqlite3
app = Flask(__name__)
@app.route('/')
def index(): #两种访问首页的路由
return render_template('index.html') # 访问 http://127.0.0.1:5000/ 返回index.html页面
@app.route('/index')
def home():
#return index() # 返回首页函数也可以到达相同的效果
return render_template('index.html') # 访问 http://127.0.0.1:5000/index 返回index.html页面
@app.route('/movie')
def movie():
return render_template('movie.html') # 访问 http://127.0.0.1:5000/movie 返回movie.html页面
@app.route('/score')
def score():
#return index() # 返回首页函数也可以到达相同的效果
return render_template('score.html') # 访问 http://127.0.0.1:5000/score 返回score.html页面
@app.route('/word')
def word():
#return index() # 返回首页函数也可以到达相同的效果
return render_template('word.html') # 访问 http://127.0.0.1:5000/word 返回word.html页面
@app.route('/team')
def team():
#return index() # 返回首页函数也可以到达相同的效果
return render_template('team.html') # 访问 http://127.0.0.1:5000/team 返回team.html页面
if __name__ == '__main__':
app.run()
到此所有页面代码基本设计完毕,开始写入数据代替页面的固定显示
电影页面数据展示
我们之前编写过豆瓣的TOP250数据提取,使用爬虫爬取并保存成sqlite3数据库db文件,我们现在打开数据库文件提取我们需要展示的数据即可
之前爬取的文章请看我的博客:
python爬虫的进阶使用:https://blog.youkuaiyun.com/qq_43422402/article/details/136006790?spm=1001.2014.3001.5502
编写movie函数功能
连接数据库提取数据库的电影数据,封装到列表里面
from flask import Flask,render_template,request
@app.route('/movie')
def movie():
datalist = []
conn = sqlite3.connect('movie.db')
cur = conn.cursor()
sql = "SELECT * FROM movie250"
data = cur.execute(sql)
for row in data:
datalist.append(row)
cur.close()
conn.close()
#return index() # 返回首页函数也可以到达相同的效果
return render_template('movie.html',moives=datalist) #指定前端页面访问电影列表的参数
提取数据渲染到页面
movies是主程序返回给前端调用数据库列表的参数,通过连接movies来渲染页面
<section id="team" class="team">
<div class="container">
<div class="section-title">
<h2>豆瓣电影TOP250详情</h2>
<p>应用Python爬虫,爬取豆瓣网经典电影top250,带你重温上个年代全球电影市场的顶尖之作</p>
</div>
<!-- ======= Counts Section ======= -->
<section class="counts section-bg">
<div class="container">
<table class="table table-striped">
<tr>
<td>排名</td>
<td>电影的中文名称</td>
<td>电影的英文名称</td>
<td>评分</td>
<td>评价人数</td>
<td>一句话概述</td>
<td>其他信息</td>
</tr>
{% for movie in moives %}
<tr>
<td>{{ movie[0] }}</td>
<td>
<a href="{{ movie[1] }}">
{{ movie[3] }}
</a>
</td>
<td>{{ movie[4] }}</td>
<td>{{ movie[5] }}</td>
<td>{{ movie[6] }}</td>
<td>{{ movie[7] }}</td>
<td>{{ movie[8] }}</td>
</tr>
{% endfor %}
</table>
</div>
</section><!-- End Counts Section -->
</div>
</section><!-- End Our Team Section -->
效果展示:
评分数据展示
在编写评分数据之前介绍一下数据展示需要用到的ECharts一种开源的数据展示模板网站,我们需要的展示方式,例如:柱状图,饼图,线型图,复合科学展示图等等他都有,而且上手简单我们来学习一下
ECharts网站
Apache ECharts一个基于 JavaScript 的开源可视化图表库网址:https://echarts.apache.org/zh/index.html
下载资源文件
开源可视化图表库JS文件:https://github.com/apache/echarts/blob/5.4.3/dist/echarts.min.js
导入JS到项目
将下载的文件放到static的js目录下 在score评价页面开头导入就行,导入代码
<script src="/static/assets/js/echarts.min.js"></script>
ECharts容器
ECharts 准备一个定义了高宽的 DOM 容器,用来显示我们的图表,很简单一个div标签搞定
<div id="main" style="width: 600px;height:400px;"></div>
JS绘制图表
不懂js的也可以写代码,我们直接打开ECharts网站,选择我们需要的模板,打开直接复制里面的代码就行,如下所示:
有这么多图形种类可以选择
喜欢那个直接点开那个,假如我们需要这个图形作为我们的设计模板,点开它是这样的
左侧就是我们需要的代码直接复制放到我们程序的末尾就行,因为script为了界面统一一般都会放到最后
评分页面的制作
我们选择我们需要的模板开始制作我们的评分页面,选择一下柱状体来展示我们的评分页面
var chartDom = document.getElementById('main');
var myChart = echarts.init(chartDom);
var option;
option = {
xAxis: {
type: 'category',
data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']
},
yAxis: {
type: 'value'
},
series: [
{
data: [120, 200, 150, 80, 70, 110, 130],
type: 'bar',
showBackground: true,
backgroundStyle: {
color: 'rgba(180, 180, 180, 0.2)'
}
}
]
};
option && myChart.setOption(option);
网站展示效果:
数据库数据渲染
@app.route('/score')
def score():
score = []
num = []
conn = sqlite3.connect('movie.db')
cur = conn.cursor()
sql = "SELECT score,count(score) FROM movie250 group by score "
data = cur.execute(sql)
# print(datalist)
for row in data:
score.append(row[0])
num.append(row[1])
#return index() # 返回首页函数也可以到达相同的效果
return render_template('score.html',score=score,num=num)
修改后的js脚本
<script type="text/javascript">
// 基于准备好的dom,初始化echarts实例
var myChart = echarts.init(document.getElementById('main'),null,{
width: 1000,
});
// 指定图表的配置项和数据
option = {
tooltip: {
trigger: 'axis',
axisPointer: {
type: 'shadow'
}
},
color:['#3398DB'],
grid: {
left: 100,
right: 1,
top: 10,
containLabel: true
},
xAxis: {
type: 'category',
data: {{ score }}
},
yAxis: {
type: 'value'
},
series: [{
data: {{ num }},
type: 'bar',
barWidth:'50%'
}]
};
// 使用刚指定的配置项和数据显示图表。
myChart.setOption(option);
</script>
x坐标是字符串的解决
上面这个score是数字型的,他渲染的页面是这样的
score.append(str(row[0])) #转化成字符串
页面没有办法正常显示
源码显示成这样
修改js为json格式
xAxis: {
type: 'category',
data: {{ score | tojson }}
},
列表也成功转换成了字符串形式的列表
词云页面的展示
词云是什么
也称为文字云,是一种数据可视化技术,它通过将文本数据中的关键词以彩色图形的形式展示,形成类似云的视觉效果。这种技术用于突出文本中出现频率较高的词汇,帮助用户快速把握文本的主旨和关键信息。词云中的每个词汇的重要性通常通过其字体大小或颜色来表示,其中出现频率较高的词汇会以较大的字体或颜色显示,而频率较低的词汇则以较小的字体或颜色显示。
词云的网站
WordCloud for Python documentation: https://amueller.github.io/word_cloud/
词云的展示形式
词云库的安装
python -m pip install wordcloud
如果不能使用pip安装按照下面的方法下载文件安装
安装其他库文件
-
numpy 是Numerical Python的简称,是高性能的科学计算和数据分析的基础包,包含了大量的矩阵和数组的计算函数
-
Matplotlib是一个 Python 的 2D 绘图库,通过 Matplotlib ,开发者可以仅需要几行代码,便可以生成折线图,直方图,条形图,饼状图,散点图等
-
PIL主要作用是图像处理,可用于图片剪切、粘贴、缩放、镜像、水印、颜色块、滤镜、图像格式转换、色场空间转换、验证码、旋转图像、图像增强、直方图处理、插值和滤波等功能。不过只支持到Python 2.7。Pillow是PIL的一个派生分支,但如今已经发展成为比PIL本身更具活力的图像处理库。我们需要安装的就是Pillow
-
jieba库是一个中文分词工具库,用于将中文文本按照词语进行切分
-
Pandas库可以快速处理大量数据,可以用于数据整理、清洗、整合、删除重复数据等操作,同时也可以方便地排序、筛选、合并、分组等操作。
import numpy as np #
from matplotlib import pyplot as plt # 绘图
from PIL import Image #处理图片
from wordcloud import WordCloud # 词云
import sqlite3
import jieba
词云生成代码
import numpy as np
from matplotlib import pyplot as plt
from PIL import Image
from wordcloud import WordCloud
import sqlite3
import jieba
# 准备好的文本
conn = sqlite3.connect('movie.db')
cur = conn.cursor()
sql = "select instroduction from movie250"
data = cur.execute(sql)
text = ""
for row in data:
text += row[0]
cur.close()
conn.close()
# 提取词组
cut = jieba.cut(text)
string = ' '.join(cut)
print(string)
# 制作词云图
img = Image.open(r'.\static\assets\img\3.png') # 打开遮罩图片
img_array = np.array(img) # 将图片转换为数组
wc = WordCloud( # 封装WordCloud对象
background_color='white',
mask=img_array,
font_path="msyh.ttc", # 字体所在位置:C:\Windows\Fonts
min_word_length=2, # 一个单词必须包含的最小字符数
stopwords=["就是", "一个", "不是", "这样", "一部", "我们", "没有", "电影", "不会", "不能", "每个"] # 屏蔽词
)
wc.generate_from_text(string) # 根据str文本生成wc词云
# 绘制图片
fig = plt.figure(1) # 绘制图片
plt.imshow(wc) # 按照词云wc的规则显示图片
plt.axis('off') # 是否显示坐标轴
# plt.show() #显示生成的词云图片
# 输出词云图片到文件
plt.savefig(r'.\static\assets\img\word.jpg',dpi=1800)
效果展示: