看到layui官网下线的消息,想起以前用layui和fastapi搭建的数据展示后台,缅怀一下,虽然很多大神觉得layui不该存在,但却是我们这些小白非常友好,感谢贤心大佬。

fastapi+layui搭建简单的数据分析后台-开水网络

为何要自己搭建数据平台?

当前的信息流平台广告归因做的比较完善,但是搜索推广平台就比较拉垮了,仅有百度ocpc配合api会反馈一些后期效果,主流的360和搜狗并没有类似功能。自己搭建数据平台连接账户推广平台和转化数据,就能回答“80%的广告费浪费在哪了?”

以前用power query+pbi,但是数据多了太卡,刷新一次数据太难,还有很多功能不能满足。

当手上账户多了以后很难实时掌握各个渠道的数据,亏了一天都不知道,知道了也不知道亏在哪里,就需要汇总一目了然。再加上账户长期更换,数据难以积累,自己搭建平台很有必要。

获取数据

首先需要获取各个账户,后期注册转化的原始数据。百度360有api接口,并且门槛低,搜狗api开通有一些要求,新户难开,用cookie可以获取。转化数据简单,找技术要api或sql都可以。

获取的原始数据用sqlIte保存,sqlIte不用搭建环境,简单便携。这里不用对数据做任何处理,确保数据的完整有效。

数据关联

也是本系统的难点,前后数据如果能轻易链接也就不用这么伤神费力了。日期、时间点、地域这些简单,账户 关键词 搜索词连接需要考虑周全。

fastapi+layui搭建简单的数据分析后台-开水网络

我这里采用的是sql查询对应的数据到pandas,在后端程序用pandas groupby汇总数据, join链接所需数据。join三四个表,数据有点慢与sql命令,但是sql命令本人实在不熟,切不好维护,放弃速度了。

数据API

数据存储后,用fastapi写接口,获取想要的数据。

def getpage(data,sum,limit,page) -> Response:
    """
    传入参数: 
    limit: int,  必须, 默认为20, 每页显示的数据量
    page: int, 必须, 默认为1, 第几页
    offset: int, 可选,默认等值于limit, 偏移量
    返回:
    json数据
    """
    offset = limit
    df2 = data[(int(page) - 1) * int(offset): (int(page) - 1) * int(offset) + int(limit)]
    df_json = df2.to_dict('records')
    return JSONResponse(
        status_code=status.HTTP_200_OK,
        content={
            'code': 0,
            'message': "Success",
            'data': df_json,
            'sum':sum,
            'count': len(data)
        }
    )


@app.get("/api/{category}")
async def read_item(category:str,channle:str="",searchParams:str="",page: int = 0, limit: int = 15):
    #category数据类别
    #searchParams筛选参数


    if searchParams !="":
        searchParams=json.loads(searchParams)
        if searchParams['st']=="":
            st="2021-10-11"
        else:
            st=searchParams['st']
        if searchParams['et']=="":
            et=time.strftime("%Y-%m-%d", time.localtime()) 
        else:
            et=searchParams['et']
        if searchParams['channle']=="":
            cquery=""
        else:
            cquery=searchParams['channle'].split(',')
        if searchParams['game']=="":
            gquery=""
        else:
            gquery=searchParams['game'].split(',')
    else:
        #如果没有筛选 设置默认
        st="2021-10-11"
        et=time.strftime("%Y-%m-%d", time.localtime()) 
        cquery=""
        gquery=""

    if category =="game":

启动命令uvicorn api:app --reload

layui展示数据

最爱layui的table简单就能达到想要的结果,配合筛选太爽了!

    layui.use(['form', 'table'], function () {
        var $ = layui.jquery,
            form = layui.form,
            table = layui.table;
            tableSelect = layui.tableSelect;


            table.render({
            elem: '#currentTableId',
            url: 'http://127.0.0.1:8000/api/game',
            toolbar: '#toolbarDemo',
            defaultToolbar: ['filter', 'exports', 'print', {
                title: '提示',
                layEvent: 'LAYTABLE_TIPS',
                icon: 'layui-icon-tips'
            }],
            cols: [[
                {type: "checkbox", width: 50},
                {field: '利润', title: '利润', sort: true},
                {field: '收益', title: '收益', sort: true},
                {field: '现金', title: '现金', sort: true},
                {field: '注册数', title: '注册数', sort: true},
                {field: '会员数', title: '会员数', sort: true},
                {field: '支付金额', title: '会员金额', sort: true},
				
            ]],
            limits: [10, 15, 20, 25, 50, 100],
            limit: 15,
            page: true,
            skin: 'line',
            done: function(data){
                    $('#stat').show();
                    $('#profit_sum').text(data.sum.profit ? data.sum.profit : 0);
                    $('#stream_sum').text(data.sum.stream ? data.sum.stream : 0);
                    $('#rmb_sum').text(data.sum.rmb ? data.sum.rmb : 0);
                    $('#vip_sum').text(data.sum.rmb ? data.sum.vip : 0);
                }
        });