在 外行學(xué) Python 爬蟲 第九篇 讀取數(shù)據(jù)庫(kù)中的數(shù)據(jù) 中完成了使用 API 從數(shù)據(jù)庫(kù)中讀取所需要的數(shù)據(jù),但是返回的是 JSON 格式,看到的是一串的字符串?dāng)?shù)據(jù)不是很好理解,這篇將介紹如何將數(shù)據(jù)進(jìn)行可視化。
數(shù)據(jù)可視化選用 pyecharts 來(lái)完成,通過(guò)將 pyecharts 集成到 Flask 中完成數(shù)據(jù)從數(shù)據(jù)庫(kù)到網(wǎng)頁(yè)可視化顯示的過(guò)程。最終完成后通過(guò)選擇框選中相應(yīng)的生產(chǎn)商后,即可查看在立創(chuàng)商城上該廠商所生產(chǎn)各種元件的數(shù)量,如下圖所示:

pyecharts 是利用 Echarts 生成圖標(biāo)的 Python 類庫(kù),是一款強(qiáng)大的數(shù)據(jù)可視化工具。更多信息請(qǐng)查閱 pyecharts 官網(wǎng)。
準(zhǔn)備工作
pyecharts 安裝
pyecharts 可使用 pip 進(jìn)行安裝
pip install pyecharts
也可以使用源碼進(jìn)行安裝
$ git clone https://github.com/pyecharts/pyecharts.git
$ cd pyecharts
$ pip install -r requirements.txt
$ python setup.py install
推薦使用 pip 進(jìn)行安裝,特別是對(duì)于初學(xué)者來(lái)說(shuō)。
集成到 Flask 中
需要將 pyecharts 中的模板拷貝到 Flask 目錄下的 templates 目錄中,模板文件位于 pyecharts/pyecharts/render/templates/目錄中。
實(shí)際上此時(shí)即可在 Flask 中使用 pyecharts 了,但是根據(jù) pyecharts 文檔中的介紹,在實(shí)際使用過(guò)程中遇到了以下錯(cuò)誤
jinja2.exceptions.TemplateNotFound: simple_chart.html
該錯(cuò)誤是由以下配置引起的
CurrentConfig.GLOBAL_ENV = Environment(loader=FileSystemLoader("./templates"))
將該配置從代碼中刪除,重新運(yùn)行程序即可看到完整的圖標(biāo)信息。
爬蟲數(shù)據(jù)可視化
在這里將完成從數(shù)據(jù)庫(kù)中讀取各生產(chǎn)商所生產(chǎn)各類元件的數(shù)據(jù),通過(guò) Echarts 進(jìn)行可視化的操作。為了實(shí)現(xiàn)能夠通過(guò)選擇生產(chǎn)商實(shí)時(shí)更新圖表數(shù)據(jù),最終使用前后端分離的方法實(shí)現(xiàn)數(shù)據(jù)顯示。
首先,先看下 HTML 文件
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Awesome-pyecharts</title>
<script src="https://cdn.bootcss.com/jquery/3.0.0/jquery.min.js"></script>
<script type="text/javascript" src="https://assets.pyecharts.org/assets/echarts.min.js"></script>
</head>
<body>
<select id="brand_name" onchange="showBrandBar()">
{% for brand in brands %}
<option value="{{brand}}">{{brand}}</option>
{% endfor %}
</select>
<div id="bar" style="width:1000px; height:600px;"></div>
<script>
$(
showBrandBar()
)
function showBrandBar() {
var selId = document.getElementById("brand_name");
var value = selId.options[selId.selectedIndex].value;
console.log(value)
postBrandBar(value)
}
function postBrandBar(brand_name) {
var chart = echarts.init(document.getElementById('bar'), 'white', {renderer: 'canvas'});
$.ajax({
type: "POST",
url: "http://127.0.0.1:5000/brand/bar",
dataType: 'json',
data:JSON.stringify({
name: brand_name
}),
success: function (result) {
chart.setOption(result);
}
});
}
</script>
</body>
</html>
采用 ajax 來(lái)響應(yīng) select 標(biāo)簽的改變事件,通過(guò) ajax 向服務(wù)端提交當(dāng)前選中的生產(chǎn)商,同時(shí)從服務(wù)器獲取該廠商的信息。可以看到在 javascrpit 腳本中默認(rèn)執(zhí)行了一次 showBrandBar() 函數(shù),是為了在第一次加載頁(yè)面時(shí)能夠正常顯示圖標(biāo),否則第一次加載頁(yè)面時(shí)圖表位置將是空白。
在 Flask 的后端需要實(shí)現(xiàn)一個(gè) get 方法和一個(gè) post 方法。get 方法用來(lái)獲取所有的生產(chǎn)商名稱,同時(shí)向?yàn)g覽器發(fā)送 html 頁(yè)面;post 方法用來(lái)相應(yīng) html 頁(yè)面中的 ajax 請(qǐng)求,發(fā)送該生產(chǎn)商所提供的各類元件的數(shù)量。
get 方法的代碼如下
def get(self):
brands = [name[0] for name in db.session.query(Brands.name).all()]
return render_template('brand_bar.html', brands=brands)
post 方法的代碼如下
def post(self):
jsons = request.get_json(force=True)
brand_name = jsons['name']
brand_id = db.session.query(Brands.id).filter(Brands.name == brand_name).one()[0]
catalog_ids = db.session.query(Catalog.id, Catalog.name).filter(Catalog.parent_id==None).all()
catalog_name = []
catalog_count = []
for cata_id, name in catalog_ids:
catalog_name.append(name)
count = db.session.query(Materials).join(Catalog).filter(
Materials.brand_id == brand_id).filter(
Catalog.parent_id == cata_id).count()
catalog_count.append(count)
c = (
Bar()
.add_xaxis(catalog_name)
.add_yaxis('數(shù)量', catalog_count)
.set_global_opts(
xaxis_opts=opts.AxisOpts(axislabel_opts=opts.LabelOpts(rotate=-90)),
title_opts=opts.TitleOpts(title=brand_name, subtitle="物料數(shù)量"),
)
)
return c.dump_options_with_quotes()
在 post 方法中主要做的是數(shù)據(jù)的查詢,通過(guò)生產(chǎn)商名稱來(lái)查詢出該生產(chǎn)商在數(shù)據(jù)中的 id,從而獲取其所提供的所有元件,然后按照 Catalog 中的分類獲取其各個(gè)分類中的元件數(shù)據(jù)。將相應(yīng)的數(shù)據(jù)填入 pyecharts 的 Bar 對(duì)象中回傳給 ajax 請(qǐng)求。
至此,執(zhí)行程序在瀏覽器中即可看到在文章開頭所看到的頁(yè)面,選擇不同的生產(chǎn)商圖標(biāo)將實(shí)時(shí)更新到該生產(chǎn)商的信息。