Python项目@基于Flask的大屏数据可视化

最后完成的效果

Python项目@基于Flask的大屏数据可视化

爬取数据

get_tencent_data()

def get_tencent_data():
"""
    :return: list全国汇总数据/日期为主键每日更新 list当日详细数据
"""

    url = "http://view.inews.qq.com/g2/getOnsInfo?name=disease_h5"
    headers = {
        'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/93.0.4577.82 Safari/537.36'
    }

    r = requests.get(url, headers)
    res = json.loads(r.text)  # json字符串-->字典
    data_all = json.loads(res['data'])

    update_time = data_all['lastUpdateTime']
    chinaTotal = data_all['chinaTotal']
    chinaAdd = data_all['chinaAdd']

    # 全国汇总历史数据

    ds = update_time.split()[0]  # 构造数据库字段
    confirm = chinaTotal['confirm']
    suspect = chinaTotal['suspect']
    heal = chinaTotal['heal']
    dead = chinaTotal['dead']
    confirm_add = chinaAdd['confirm']
    suspect_add = chinaAdd['suspect']
    heal_add = chinaAdd['heal']
    dead_add = chinaAdd['dead']
    history = [ds, confirm, confirm_add, suspect, suspect_add, heal, heal_add, dead, dead_add]

    # 全国各省市当日详情数据
    details = []

    data_province = data_all['areaTree'][0]['children']  # 中国各省

    for pro_infos in data_province:

        province = pro_infos['name']  # 省

        for city_infos in pro_infos['children']:
            city = city_infos['name']  # 市

            confirm = city_infos['total']['confirm']
            confirm_add = city_infos['today']['confirm']
            heal = city_infos['today']['confirm']
            dead = city_infos['total']['dead']
            details.append([update_time, province, city, confirm, confirm_add, heal, dead])

    return history, details

def get_baidu_hot()

这里我们用到了 selenium模块,它可以爬取到用 ajax请求的数据。还能直接用鼠标选取标签定位。

def get_baidu_hot():
"""
    :return: 返回百度热搜前30中的28个
"""

    options = webdriver.FirefoxOptions()
    options.add_argument("--headless")  # 隐藏浏览器弹窗
    options.add_argument("--disable-gpu")

    browser = webdriver.Firefox(options=options)
    browser.get('https://top.baidu.com/board?tab=realtime')
    r = browser.find_elements_by_xpath('//*[@id="sanRoot"]/main/div[2]/div/div[2]')  # F12 选中元素右键 copy 得到 Xpath

    hot_data = [i.text.split("\n") for i in r]

    hot_list = []
    n = 0

    for e in hot_data[0]:
        if e == '热' or e == '新' or e == '沸':
            hot_data[0].remove(e)
        else:
            n += 1
            if n % 5 == 0:
                hot_list.append(hot_data[0][
                                n - 5: n])  # ['1', '4992729', '热搜指数', '河北大巴坠河事故致14人遇难', '10月11日,河北石家庄市平山县一辆载51人的大巴车落水。截至12日下午2时40分,最后一名失联人员被找到,已无生命体征... 查看更多>']

    return hot_list

保存数据到数据库

创建数据库/表

各个字段含义(history)

+————-+——————–+———–+
| column_name | column_comment | data_type |
+————-+——————–+———–+
| ds | 日期 | datetime |
| confirm | 累计确诊 | int |
| confirm_add | 当日新增确诊 | int |
| suspect | 剩余疑似 | int |
| suspect_add | 当日新增疑似 | int |
| heal | 累计治愈 | int |
| heal_add | 当日新增治愈 | int |
| dead | 累计死亡 | int |
| dead_add | 当日新增死亡 | int |
+————-+——————–+———–+

#mysql 安装https://blog.51cto.com/u_12226796/2431965

#建表

#bdhot
create table bdhot(
id int(11) not null auto_increment,
dt timestamp default current_timestamp,# 默认值为当前时间
hotrank int(11) default null,
hotscore int(11) default null,
title varchar(255) default null,
content tinytext default null,
primary key(id) using btree
)engine=innodb default charset=utf8mb4;

#history

create table history(
ds datetime not null comment'日期',
confirm int(11) default null comment'累计确诊',
confirm_add int(11) default null comment'当日新增确诊',
suspect int(11) default null comment'剩余疑似',
suspect_add int(11) default null comment'当日新增疑似',
heal int(11) default null comment'累计治愈',
heal_add int(11) default null comment'当日新增治愈',
dead int(11) default null comment'累计死亡',
dead_add int(11) default null comment'当日新增死亡',
primary key(ds) using btree
)engine=innodb default charset=utf8mb4;

#details

create table details(
id int(11) not null auto_increment,
update_time datetime not null comment'数据最后更新时间',
province varchar(50) default null comment'省',
city varchar(50) default null comment'市',
confirm int(11) default null comment'累计确诊',
confirm_add int(11) default null comment'新增确诊',
heal int(11) default null comment'累计治愈',
dead int(11) default null comment'累计死亡',
primary key(id) using btree
)engine=innodb default charset=utf8mb4;

def update_details()

def update_details():
"""
    更新 details 表
    :return:
"""

    cursor = None
    conn = None

    try:
        #li = get_tencent_data()[1]  # 0 是历史数据字典, 1 最新详细数据列表
        li = get_tencent_data()[1]
        conn, cursor = get_conn()

        sql = "insert into details(update_time, province, city, confirm, confirm_add, heal, dead) values(%s, %s, %s, %s, %s, %s, %s)"
        sql_query = 'select %s=(select update_time from details order by id desc limit 1)'  # 对比当前最大时间戳 当前数据时间和最大时间相等返回 1 不等返回 0

        cursor.execute(sql_query, li[0][0])  # 随便取一个元素的时间

        if not cursor.fetchone()[0]:
            print(f"{time.asctime()}详细数据开始更新......")
            for item in li:
                # print(item)
                cursor.execute(sql, item)

            conn.commit()  # 提交事务 update delete insert 操作

            print(f"{time.asctime()}详细数据更新完毕。")
        else:
            print(f"{time.asctime()}详细数据已是最新 !")

    except:
        traceback.print_exc()  # 打印异常信息
    finally:
        close_conn(conn, cursor)

def update_history()

def update_history():
"""
    插入历史数据, 第一次运行项目直接插入
    :return:
"""

    cursor = None
    conn = None

    try:
        hlist = get_tencent_data()[0]  # 0 是历史数据字典, 1 最新详细数据列表
        print(f"{time.asctime()}历史数据开始插入......")
        # print(hlist)
        conn, cursor = get_conn()

        sql = "insert into history values(%s,%s,%s,%s,%s,%s,%s,%s,%s)"
        sql_query = 'select %s=(select ds from history order by ds desc limit 1)'  # 对比当前最大时间戳 当前数据时间和最大时间相等返回 1 不等返回 0

        cursor.execute(sql_query, time.strftime("%Y-%m-%d 00:00:00"))  # 随便取一个元素的时间

        if not cursor.fetchone()[0]:
            cursor.execute(sql, hlist)

            conn.commit()
            print(f"{time.asctime()}历史数据更新完毕。")
        else:
            print(f"{time.asctime()}历史数据已是最新 !")
    except:
        traceback.print_exc()
    finally:
        close_conn(conn, cursor)

def update_baidu_hot():

def update_baidu_hot():
"""
    插入百度热搜数据
    :return:
"""

    cursor = None
    conn = None

    hot_list = get_baidu_hot()

    print(f"{time.asctime()}百度热搜数据开始更新......")
    try:
        conn, cursor = get_conn()
        sql = "insert into bdhot(hotrank, hotscore, title, content) values(%s, %s, %s, %s)"
        for hot in hot_list:

            hotrank = int(hot[0])
            hotscore = int(hot[1])
            title = hot[3]
            content = hot[4]

            tup = (hotrank, hotscore, title, content)
            # print(tup)
            cursor.execute(sql, tup)
        conn.commit()
        print(f"{time.asctime()}百度热搜数据更新完成。")
    except:
        traceback.print_exc()
    finally:
        close_conn(conn, cursor)

前端布局

HTML

我们用了很多echarts的图表模板。

<!DOCTYPE html>
<html lang>
    <head>
        <meta charset="utf-8">
        <title>&#x5168;&#x56FD;&#x75AB;&#x60C5;&#x8FFD;&#x8E2A;</title>

        <script src="../static/js/jquery-1.11.1.min.js"></script>
        <script src="../static/js/echarts.min.js"></script>
        <script src="../static/js/china.js"></script>
        <script src="../static/js/echarts-wordcloud.min.js"></script>

        <link href="../static/css/main.css" rel="stylesheet">

    </head>
    <body>
        <div id="title">&#x5168;&#x56FD;&#x75AB;&#x60C5;&#x8FFD;&#x8E2A;</div>

        <div id="mid-1">

            <div class="txt"><h3>&#x7D2F;&#x8BA1;&#x786E;&#x8BCA;</h3></div>
            <div class="txt"><h3>&#x5269;&#x4F59;&#x7591;&#x4F3C;</h3></div>
            <div class="txt"><h3>&#x7D2F;&#x8BA1;&#x6CBB;&#x6108;</h3></div>
            <div class="txt"><h3>&#x7D2F;&#x8BA1;&#x6B7B;&#x4EA1;</h3></div>
        </div>

        <!--mid-2 中国地图 -->
        <script src="../static/js/ec_mid2.js"></script>

        <!--left-1 全国趋势 -->
        <script src="../static/js/ec_left1.js"></script>
        <!--left-2 新增趋势 -->
        <script src="../static/js/ec_left2.js"></script>

        <!--right-1 确诊前五 -->
        <script src="../static/js/ec_right1.js"></script>
        <!--right-1 百度热搜词云 -->
        <script src="../static/js/ec_right2.js"></script>

        <!--ajax 动态请求 -->
        <script src="../static/js/ajax_func.js"></script>
    </body>
</html>

CSS

简单粗暴的绝对定位。hhh…

body{
    margin: 0;
    background-color: #100c2a;
}

#top{
    position: absolute;
    width: 100%;
    height: 10%;
    top: 0;
    left: 0;
    right: 0;
    /* background-color: pink; */
    color: white;
    font-size: 30px;
    font-family: "&#x5E7C;&#x5706;";

    display: flex;  /* &#x5F39;&#x6027;&#x5E03;&#x5C40; */
    align-items: center;
    justify-content: center;

}

#info{
    position: absolute;
    width: 50%;
    height: 21%;
    top: 10%;
    left: 0%;
    right: 75%;
    color: white;
    /* background-color: cadetblue; */
}

#block-1{
    position: absolute;
    width: 25%;
    height: 21%;
    top: 31%;
    left: 0%;
    right: 75%;
    color: white;
    background-color: blueviolet;
}

#block-2{
    position: absolute;
    width: 25%;
    height: 21%;
    top: 52%;
    left: 0%;
    right: 75%;
    color: white;
    background-color: greenyellow;
}

#block-3{
    position: absolute;
    width: 25%;
    height: 21%;
    top: 73%;
    left: 0%;
    right: 75%;
    color: white;
    background-color: brown;
}

#foot{
    position: absolute;
    width: 100%;
    height: 6%;
    top: 94%;
    left: 0%;
    right: 0%;
    color: ghostwhite;
    /* background-color: pink; */
}

ajax 局部动态请求

ajax 可局部的请求页面的某个模块,避免刷新整个页面浪费资源。
为了代码美观容易阅读,我们把所有ajax写到同一个文件中。

// div top-2 &#x540E;&#x53F0;&#x65F6;&#x95F4;
function get_top2_time(){
    $.ajax({
        url:"/time",
        timeout:10000,  // &#x8D85;&#x65F6;&#x65F6;&#x95F4; 10s
        success:function(data){
            $("#top-2").html(data)
        },
        error: function(xhr, type, errThrown){

        }
    });
}

// div mid-1 &#x7B80;&#x7565;&#x603B;&#x8BA1;
function get_mid1_data(){
    $.ajax({
        url:"/mid1",
        success:function(mid1_data){
            $(".num h2").eq(0).text(mid1_data.confiirm);
            $(".num h2").eq(1).text(mid1_data.suspect);
            $(".num h2").eq(2).text(mid1_data.heal);
            $(".num h2").eq(3).text(mid1_data.dead);
        },
        error: function(xhr, type, errThrown){

        }
    });
}

// div mid-2 &#x5404;&#x7701;&#x6570;&#x636E;
function get_mid2_data() {
    $.ajax({
        url:"/mid2",
        success:function(mid2_data){
            ec_center_option.series[0].data = mid2_data.data
            ec_center.setOption(ec_center_option)
        },
        error: function(xhr, type, errThrown){

        }
    });
}

// div left-1 &#x7D2F;&#x8BA1;&#x8D8B;&#x52BF;

function get_left1_data(){
    $.ajax({
        url: "/left1",
        success: function(left1_data) {
            ec_left1_Option.xAxis[0].data=left1_data.day

            ec_left1_Option.series[0].data=left1_data.confirm
            ec_left1_Option.series[1].data=left1_data.suspect
            ec_left1_Option.series[2].data=left1_data.heal
            ec_left1_Option.series[3].data=left1_data.dead
            ec_left1.setOption(ec_left1_Option)

        },
        error: function(xhr, type, errThrown){

        }
    });
}

// div left-2 &#x65B0;&#x589E;&#x8D8B;&#x52BF;

function get_left2_data(){
    $.ajax({
        url: "/left2",
        success: function(left2_data) {
            ec_left2_Option.xAxis[0].data=left2_data.day

            ec_left2_Option.series[0].data=left2_data.confirm_add
            ec_left2_Option.series[1].data=left2_data.suspect_add
            ec_left2_Option.series[2].data=left2_data.heal_add
            ec_left2_Option.series[3].data=left2_data.dead_add

            ec_left2.setOption(ec_left2_Option)

        },
        error: function(xhr, type, errThrown){

        }
    });
}

// div right-1 Top5

function get_right1_data(){
    $.ajax({
        url: "/right1",
        success: function(right1_data) {

            ec_right1_Option.xAxis.data=right1_data.city

            ec_right1_Option.series[0].data=right1_data.confirm

            ec_right1.setOption(ec_right1_Option)

        },
        error: function(xhr, type, errThrown){

        }
    });
}

// div right-2 &#x8BCD;&#x4E91;

function get_right2_data(){
    $.ajax({
        url: "/right2",
        success: function(right2_data) {

            ec_right2_Option.series[0].data=right2_data.kws

            ec_right2.setOption(ec_right2_Option)

        },
        error: function(xhr, type, errThrown){

        }
    });
}
// setInterval(gettime, 1000)  // &#x4E00;&#x79D2;&#x949F;&#x6267;&#x884C;&#x4E00;&#x6B21;
// setInterval(get_mid1_data, 1000)
// setInterval(get_mid2_data, 1000)

get_top2_time()

get_mid1_data()
get_mid2_data()

get_left1_data()
get_left2_data()

get_right1_data()
get_right2_data()

// &#x5237;&#x65B0;&#x9891;&#x7387;
setInterval(get_top2_time, 1000)
setInterval(get_right2_data, 1000*10)

从数据库中请求数据

-*- coding: utf-8 -*-
@Time     : 2021/10/14 22:24
@Author   : JustFly
@File     : func.py
@Software : PyCharm

import requests
import json
import time
import pymysql
import traceback
from selenium import webdriver

def get_conn():
"""
    :return: &#x8FDE;&#x63A5;, &#x6E38;&#x6807;
"""
    # &#x521B;&#x5EFA;&#x8FDE;&#x63A5;
    conn = pymysql.connect(host="127.0.0.1",
                           user="root",
                           password="123456",
                           db="covid_2019",
                           )
    # &#x521B;&#x5EFA;&#x6E38;&#x6807;
    cursor = conn.cursor()
    return conn, cursor

def close_conn(conn, cursor):
    if cursor:
        cursor.close()
    if conn:
        conn.close()

def query(sql, *args):
"""
    &#x5C01;&#x88C5;&#x901A;&#x7528;&#x67E5;&#x8BE2;
    :param sql:
    :param args:
    :return:&#x5143;&#x7EC4;
"""
    conn, cursor = get_conn()
    cursor.execute(sql, args)
    res = cursor.fetchall()
    # print(res)
    close_conn(conn, cursor)
    return res

def get_top2_time():
    time_str = time.strftime(f"%Y{{}}%m{{}}%d{{}} %X")  # &#x4E0D;&#x652F;&#x6301;&#x8BC6;&#x522B;&#x4E2D;&#x6587; {}&#x7AD9;&#x4F4D;
    return time_str.format("&#x5E74;", "&#x6708;", "&#x65E5;")

def get_mid1_data():
"""
    :return: &#x8FD4;&#x56DE;&#x5168;&#x56FD;&#x603B;&#x8BA1;&#x6570;&#x636E;&#x4F9B; div id = "mid-1" &#x4F7F;&#x7528;
"""
    # sql = "select sum(confirm)," \
    #       "(select suspect from history order by ds desc limit 1)," \
    #       "sum(heal)," \
    #       "sum(dead)" \
    #       "from details;"

    sql = "select confirm, suspect, heal, dead from history order by ds desc limit 1;"

    res = query(sql)
    # print(res)
    return res[0]

def get_mid2_data():
"""
    :return: &#x8FD4;&#x56DE;&#x4E2A;&#x7701;&#x6570;&#x636E;&#x4F9B; div id = "mid-2" &#x4F7F;&#x7528;
"""
    sql = "select province, sum(confirm) from details " \
          "where update_time=(select update_time from details order by update_time desc limit 1)" \
          "group by province"

    res = query(sql)
    return res

def get_left1_data():
"""
    :return:&#x5168;&#x56FD;&#x7D2F;&#x8BA1;&#x8D8B;&#x52BF;&#x6570;&#x636E;
"""
    sql = "select ds, confirm, suspect, heal, dead from history"
    res = query(sql)
    return res

def get_left2_data():
"""
    :return:&#x5168;&#x56FD;&#x65B0;&#x589E;&#x8D8B;&#x52BF;&#x6570;&#x636E;
"""
    sql = "select ds, confirm_add, suspect_add, heal_add, dead_add from history"
    res = query(sql)
    return res

def get_right1_data():
"""
    :return: &#x786E;&#x8BCA;&#x524D;&#x4E94;&#x975E;&#x6E56;&#x5317;&#x57CE;&#x5E02;
"""
    # &#x9664;&#x53BB;&#x76F4;&#x8F96;&#x5E02;&#xFF0C;&#x56E0;&#x4E3A;&#x5B83;&#x91CC;&#x9762;&#x76F4;&#x63A5;&#x662F;&#x67D0;&#x67D0;&#x533A;&#x800C;&#x975E;&#x5E02;
    sql = "select city, confirm from" \
          "(" \
          "select city, confirm from details where update_time=(select update_time from details order by update_time desc limit 1)" \
          "and province not in ('&#x53F0;&#x6E7E;', '&#x6E56;&#x5317;', '&#x5317;&#x4EAC;', '&#x4E0A;&#x6D77;', '&#x5929;&#x6D25;', '&#x91CD;&#x5E86;')" \
          "union all " \
          "select province as city, sum(confirm) as confirm from details " \
          "where update_time=(select update_time from details order by update_time desc limit 1)" \
          "and province in ('&#x5317;&#x4EAC;', '&#x4E0A;&#x6D77;', '&#x5929;&#x6D25;', '&#x91CD;&#x5E86;') group by province" \
          ") as a " \
          "where city not in ('&#x5883;&#x5916;&#x8F93;&#x5165;', '&#x5730;&#x533A;&#x5F85;&#x786E;&#x8BA4;') " \
          "order by confirm desc limit 5"

    res = query(sql)

    return res

def get_right2_data():
"""
    :return: &#x8FD4;&#x56DE;&#x6700;&#x8FD1;20&#x6761;&#x70ED;&#x641C;
"""
    sql = "select title, hotscore from bdhot order by id desc limit 20"
    res = query(sql)

    return res

get_right2_data()

Flask路由逻辑

import string

from flask import Flask
from flask import request
from flask import render_template
import func
from flask import jsonify  # json &#x8F6C; dict
from jieba.analyse import extract_tags

app = Flask(__name__)  # &#x521B;&#x5EFA;&#x4E00;&#x4E2A;Flash&#x5B9E;&#x4F8B;

@app.route("/")
def main():
    return render_template("main.html")

@app.route("/time")
def get_top2_time():
    return func.get_top2_time()

@app.route("/mid1")
def get_mid1_data():
    data = func.get_mid1_data()
    dic = {"confiirm": data[0], "suspect": data[1], "heal": data[2], "dead": data[3]}
    return jsonify(dic)

@app.route("/mid2")
def get_mid2_data():
    res = []
    for tup in func.get_mid2_data():
        dic = {"name": tup[0], "value": int(tup[1])}
        res.append(dic)
    print(res)
    return jsonify({"data": res})

@app.route("/left1")
def get_left1_data():
    data = func.get_left1_data()
    day, confirm, suspect, heal, dead = [], [], [], [], []
    for d in data:
        day.append(d[0].strftime("%m-%d"))
        confirm.append(d[1])
        suspect.append(d[2])
        heal.append(d[3])
        dead.append(d[4])
    dic = {"day": day, "confirm": confirm, "suspect": suspect, "heal": heal, "dead": dead}
    print(dic)
    return jsonify(dic)

@app.route("/left2")
def get_left2_data():
    data = func.get_left2_data()
    day, confirm_add, suspect_add, heal_add, dead_add = [], [], [], [], []
    for d in data:
        day.append(d[0].strftime("%m-%d"))

        confirm_add.append(d[1])
        suspect_add.append(d[2])
        heal_add.append(d[3])
        dead_add.append(d[4])

    dic = {"day": day, "confirm_add": confirm_add, "suspect_add": suspect_add, "heal_add": heal_add, "dead_add": dead_add}
    print(dic)
    return jsonify(dic)

@app.route("/right1")
def get_right1_data():
    data = func.get_right1_data()
    city = []
    confirm = []

    for d in data:
        city.append(d[0])
        confirm.append(int(d[1]))

    dic = {"city": city, "confirm": confirm}
    # print(dic)
    return jsonify(dic)

@app.route("/right2")
def get_right2_data():
    data = func.get_right2_data()  # (('&#x822A;&#x5929;&#x5458;&#x592A;&#x7A7A;&#x8FC7;&#x5E74;&#x5403;&#x5565;&#x9985;&#x997A;&#x5B50;?', 4962929), ('&#x5357;&#x5317;&#x65B9;&#x5C06;&#x8FCE;&#x4E0B;&#x534A;&#x5E74;&#x6765;&#x6700;&#x51B7;&#x6E05;&#x6668;', 4829320),....,)
    d = []
    for i in data:
        k, v = i[0], i[1]
        ks = extract_tags(k)  # &#x4F7F;&#x7528;jieba&#x63D0;&#x53D6;&#x5173;&#x952E;&#x5B57;

        for j in ks:
            if not j.isdigit():
                d.append({"name": j, "value": str(v)})
    # print(d)
    return jsonify({"kws": d})

if __name__ == '__main__':
    app.run()

部署项目到服务器

注意:
1.修改连接的数据库信息
2.修改 app.py
app.run() => app.run(host=0.0.0.0, port=5000)
3. python3 app.py可用此命令用于调试,退出命令行界面后失效。 安装

yum install nginx  # &#x5B89;&#x88C5; nginx

pip install gunicorn # &#x5B89;&#x88C5; gunicorn

配置Nginx做反向代理 vim /etc/nginx/nginx.conf

sever 上添加 服务器集群 和权重 ,我只有一台服务器就写一个(127.1我写的是内网ip)。

upstream mycluster {

    server 127.0.0.1:5000 weight=1;

}

&#x3002;&#x3002;&#x3002;&#x3002;

&#x200B;

include /etc/nginx/conf.d/*.conf;

    upstream mycluster{

                server 172.17.0.15:5000 weight=1;

                }

    server {

        listen       80 default_server;

        listen       [::]:80 default_server;

        server_name  172.17.0.15;

        root         /usr/share/nginx/html;

&#x3002;&#x3002;&#x3002;&#x3002;

启动服务器 gunicorn -b 127.0.0.1:5000 -D app:app

[root@VM-0-15-centos COVID19]# gunicorn -b 172.17.0.15:5000 -D app:app

[root@VM-0-15-centos COVID19]# ps -ef | grep gunicorn

root       25252       1  0 16:45 ?        00:00:00 /usr/bin/python3.6 /usr/local/bin/gunicorn -b 172.17.0.15:5000 -D app:app

root       25255   25252  5 16:45 ?        00:00:00 /usr/bin/python3.6 /usr/local/bin/gunicorn -b 172.17.0.15:5000 -D app:app

root       25298   20928  0 16:46 pts/3    00:00:00 grep --color=auto gunicorn

[root@VM-0-15-centos COVID19]#

[root@VM-0-15-centos COVID19]#

[root@VM-0-15-centos COVID19]#

[root@VM-0-15-centos COVID19]#

用crotab设置定时更新脚本

[root@VM-0-15-centos COVID19]# crontab -l

*/5 * * * * flock -xn /tmp/stargate.lock -c '/usr/local/qcloud/stargate/admin/start.sh > /dev/null 2>&1 &'

* */12 * * * python3 /root/COVID19/update.py up_all >> /root/COVID19/covid19.log 2>&1 &

5 */1 * * *  python3 /root/COVID19/update.py up_hot >> /root/COVID19/covid19.log 2>&1 &

&#x200B;

[root@VM-0-15-centos COVID19]#

[root@VM-0-15-centos COVID19]#

[root@VM-0-15-centos COVID19]#

[root@VM-0-15-centos COVID19]#

[root@VM-0-15-centos COVID19]# crontab -e

启动 Nginx

/usr/sbin/nginx

参考

bilibili

Original: https://blog.csdn.net/qq_45809480/article/details/125655681
Author: JIJIFI
Title: Python项目@基于Flask的大屏数据可视化

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/744671/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

  • bugrobot用6行代码调用微信报警机器人

    算法工程师常常会为监控代码而头痛,有些代码执行时间常常会长达数小时,甚至几天。 例如一些机器学习模型的训练,以及一些大数据ETL任务。 如果能够将执行过程中的一些中间重要信息发送到…

    Python 2023年8月5日
    062
  • Python如何搭建疫苗管理系统

    Original: https://www.cnblogs.com/123456feng/p/16026839.htmlAuthor: 蚂蚁ailingTitle: Python如…

    Python 2023年11月9日
    059
  • Rstudio导入conda环境中的R之惨痛教训 找不到libbz2-1.dll

    Rstudio 千万不要导入conda 中的R 由于在anaconda中安装R studio一直报错,提示各种文件安装出错,又想使用conda中的R包,于是就尝试导入的Anacon…

    Python 2023年9月9日
    059
  • jsp调用python脚本_Python实现从脚本里运行scrapy的方法

    本文实例讲述了Python实现从脚本里运行scrapy的方法。分享给大家供大家参考。具体如下: !/usr/bin/python import os os.environ.setd…

    Python 2023年10月4日
    042
  • Django restframework实现批量操作

    这篇文章主要介绍两种方式实现 &#x6279;&#x91CF;&#x64CD;&#x4F5C;, 一种是使用 Django restframewor…

    Python 2023年8月3日
    056
  • 【Django4】django项目创建的步骤

    打开cmd安装Django框架:【pip install django】默认安装最新版4.0.4 创建一个空的文件夹用于存放Django项目 :【mydjango】 直接在框里所在…

    Python 2023年8月5日
    061
  • 爬虫系列:爬虫验证码识别

    虽然大多数人对单词”CAPTCHA”都很熟悉,但是很少人知道它的具体含义:全自动区分计算机和人类的图灵测试(Completely Automated Pub…

    Python 2023年11月3日
    034
  • 43. Pandas查询数据的简便方法df.query

    Pandas查询数据的简便方法df.query 怎样进行复杂组合条件对数据查询: 方式1. 使用df[(df[“a”] > 3) & (df[…

    Python 2023年8月20日
    034
  • Python 在Pycharm中连接 MySQL数据库

    1、View —- > Tool windows — > Database 2、DataSource —- > MySQL 3…

    Python 2023年5月24日
    072
  • Pytorch学习笔记(1)检查torch、cuda,张量的创建

    lesson1 检查torch、cuda import torch print("Hello World, Hello PyTorch {}".format(t…

    Python 2023年8月29日
    062
  • Kafka详解

    Kafka介绍 Kafka是最初由Linkedin公司开发,是一个分布式、支持分区的(partition)、多副本的(replica),基于zookeeper协调的分布式消息系统,…

    Python 2023年10月19日
    043
  • pandas复习

    基础复习 下载软件与核验:工欲善其事必先利其器,学习要求下载anaconda和xlrd,并且pandas的版本号不低于1.6。查看pandas的版本的方法: import pand…

    Python 2023年8月7日
    071
  • O2O优惠券数据分析(二)

    写在前面的话 本文中部分数据分析逻辑继承于O2O优惠券数据分析(一),如对文中部分数据处理和分析逻辑有问题,可先阅读前文。本文将主要负责分析线上用户行为及线上和线下共同用户的行为。…

    Python 2023年8月18日
    045
  • 防火墙nat豁免与控制原理讲解

    ♥️ 作者:小刘在C站♥️ 每天分享云计算网络运维课堂笔记,疫情之下,你我素未谋面,但你一定要平平安安,一 起努力,共赴美好人生!♥️ 夕阳下,是最美的,绽放,愿所有的美好,再疫情…

    Python 2023年9月26日
    051
  • 12.23

    node.js 38-51 Express 1.基于node.js平台的web开发框架 类似于内置的http模块 用来创建web服务器 2.对外提供静态资源(存疑) 3.路由:客户…

    Python 2023年9月16日
    043
  • Python制作粒子烟花,提前开始跨年?

    前言 跨年倒计时20天?我已经开始整烟花了,虽然不是很好看吧,但是也能将就看看 😥 这个的背景图,音乐,还有文字都是可以自己修改的哦 效果展示 ; 导入库 import rando…

    Python 2023年8月12日
    049
亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球