数据可视化:利用Python和Echarts制作“用户消费行为分析”可视化大屏

  • 前言
    • 实验目的:
    • 准备工作:
  • 一、创建项目:
  • 二、建立数据库连接获取数据:
  • 三、页面布局:
  • 四、下载ECharts、jQuery等JS库文件:
  • 五、在官网找到需要的模板并为每个问题编写JS文件:
    • 5.1 创建问题一JS文件命名为ec_left_1.js
    • 5.2 创建问题二JS文件命名为ec_left_2.js
    • 5.3 创建问题三JS文件命名为ec_center.js
    • 5.4 创建问题四JS文件命名为ec_right_1.js
    • 5.5 创建问题五JS文件命名为ec_right_2.js
    • 5.6 去模板文件里建立JS文件的连接
  • 六、使用Flask创建路由,并把数据处理成需要的格式:
    • 6.1 问题一、二的路由创建以及数据格式转换
    • 6.2 问题三的路由创建以及数据格式转换
    • 6.3 问题四的路由创建以及数据格式转换
    • 6.4 问题五的路由创建以及数据格式转换
  • 七、编写Ajax获取数据传给对应问题的JS文件:
  • 八、运行调试:
  • 九、总结:

前言

暑假这段时间参加了一个学校的小培训,培训布置的项目“用户消费行为分析应用案例”。从开始的数据预处理到数据分析再到最后的数据可视化。原计划一个月完成的项目,奈何自己太菜,一直拖到现在才算勉强完成(因为完成的不算完美)。博客也是从这个培训开始写,从最开始用pandas进行数据预处理开始,再到后边的hive数据分析,再到这篇ECharts可视化,从中间学到了不少东西,也花费了不少心力,看起来很简单的东西实际操作起来错误频出,感觉自己好菜啊,希望自己越来越强OwO


前几篇文章地址:
使用pandas进行数据预处理
使用Hive进行数据分析以及将分析后的数据导入MySQL数据库


注意:

  1. 涉及到的知识有:Python,Flask,Ajax,js,jQuery,ECharts等;
  2. 如果使用文章里的代码,表名,引用的文件名字等需要根据实际进行修改;
  3. 实际执行过程中可能会遇到各种各样的问题,可以评论如果我知道我会解答,不知道我可以和你一起找解决办法;
  4. 因为这里用了一个前边文章里没有写的两个表,所以我把这两个表的生成写在了这里;
  5. 需结合上篇博客的数据分析使用,或自己创建表。

实验目的:

用Python进行数据可视化分析
展示业务量:

  1. 双十二当天的各个省的发货量。
  2. 每天的浏览量和购买量。
  3. 每天的购买率。
  4. 双十二当天top10的用户信息(包括:useid,购买数量,省份)

大致流程:

#mermaid-svg-cE5iQzO0yoEdIZFg .label{font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family);fill:#333;color:#333}#mermaid-svg-cE5iQzO0yoEdIZFg .label text{fill:#333}#mermaid-svg-cE5iQzO0yoEdIZFg .node rect,#mermaid-svg-cE5iQzO0yoEdIZFg .node circle,#mermaid-svg-cE5iQzO0yoEdIZFg .node ellipse,#mermaid-svg-cE5iQzO0yoEdIZFg .node polygon,#mermaid-svg-cE5iQzO0yoEdIZFg .node path{fill:#ECECFF;stroke:#9370db;stroke-width:1px}#mermaid-svg-cE5iQzO0yoEdIZFg .node .label{text-align:center;fill:#333}#mermaid-svg-cE5iQzO0yoEdIZFg .node.clickable{cursor:pointer}#mermaid-svg-cE5iQzO0yoEdIZFg .arrowheadPath{fill:#333}#mermaid-svg-cE5iQzO0yoEdIZFg .edgePath .path{stroke:#333;stroke-width:1.5px}#mermaid-svg-cE5iQzO0yoEdIZFg .flowchart-link{stroke:#333;fill:none}#mermaid-svg-cE5iQzO0yoEdIZFg .edgeLabel{background-color:#e8e8e8;text-align:center}#mermaid-svg-cE5iQzO0yoEdIZFg .edgeLabel rect{opacity:0.9}#mermaid-svg-cE5iQzO0yoEdIZFg .edgeLabel span{color:#333}#mermaid-svg-cE5iQzO0yoEdIZFg .cluster rect{fill:#ffffde;stroke:#aa3;stroke-width:1px}#mermaid-svg-cE5iQzO0yoEdIZFg .cluster text{fill:#333}#mermaid-svg-cE5iQzO0yoEdIZFg div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family);font-size:12px;background:#ffffde;border:1px solid #aa3;border-radius:2px;pointer-events:none;z-index:100}#mermaid-svg-cE5iQzO0yoEdIZFg .actor{stroke:#ccf;fill:#ECECFF}#mermaid-svg-cE5iQzO0yoEdIZFg text.actor>tspan{fill:#000;stroke:none}#mermaid-svg-cE5iQzO0yoEdIZFg .actor-line{stroke:grey}#mermaid-svg-cE5iQzO0yoEdIZFg .messageLine0{stroke-width:1.5;stroke-dasharray:none;stroke:#333}#mermaid-svg-cE5iQzO0yoEdIZFg .messageLine1{stroke-width:1.5;stroke-dasharray:2, 2;stroke:#333}#mermaid-svg-cE5iQzO0yoEdIZFg #arrowhead path{fill:#333;stroke:#333}#mermaid-svg-cE5iQzO0yoEdIZFg .sequenceNumber{fill:#fff}#mermaid-svg-cE5iQzO0yoEdIZFg #sequencenumber{fill:#333}#mermaid-svg-cE5iQzO0yoEdIZFg #crosshead path{fill:#333;stroke:#333}#mermaid-svg-cE5iQzO0yoEdIZFg .messageText{fill:#333;stroke:#333}#mermaid-svg-cE5iQzO0yoEdIZFg .labelBox{stroke:#ccf;fill:#ECECFF}#mermaid-svg-cE5iQzO0yoEdIZFg .labelText,#mermaid-svg-cE5iQzO0yoEdIZFg .labelText>tspan{fill:#000;stroke:none}#mermaid-svg-cE5iQzO0yoEdIZFg .loopText,#mermaid-svg-cE5iQzO0yoEdIZFg .loopText>tspan{fill:#000;stroke:none}#mermaid-svg-cE5iQzO0yoEdIZFg .loopLine{stroke-width:2px;stroke-dasharray:2, 2;stroke:#ccf;fill:#ccf}#mermaid-svg-cE5iQzO0yoEdIZFg .note{stroke:#aa3;fill:#fff5ad}#mermaid-svg-cE5iQzO0yoEdIZFg .noteText,#mermaid-svg-cE5iQzO0yoEdIZFg .noteText>tspan{fill:#000;stroke:none}#mermaid-svg-cE5iQzO0yoEdIZFg .activation0{fill:#f4f4f4;stroke:#666}#mermaid-svg-cE5iQzO0yoEdIZFg .activation1{fill:#f4f4f4;stroke:#666}#mermaid-svg-cE5iQzO0yoEdIZFg .activation2{fill:#f4f4f4;stroke:#666}#mermaid-svg-cE5iQzO0yoEdIZFg .mermaid-main-font{font-family:"trebuchet ms", verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-cE5iQzO0yoEdIZFg .section{stroke:none;opacity:0.2}#mermaid-svg-cE5iQzO0yoEdIZFg .section0{fill:rgba(102,102,255,0.49)}#mermaid-svg-cE5iQzO0yoEdIZFg .section2{fill:#fff400}#mermaid-svg-cE5iQzO0yoEdIZFg .section1,#mermaid-svg-cE5iQzO0yoEdIZFg .section3{fill:#fff;opacity:0.2}#mermaid-svg-cE5iQzO0yoEdIZFg .sectionTitle0{fill:#333}#mermaid-svg-cE5iQzO0yoEdIZFg .sectionTitle1{fill:#333}#mermaid-svg-cE5iQzO0yoEdIZFg .sectionTitle2{fill:#333}#mermaid-svg-cE5iQzO0yoEdIZFg .sectionTitle3{fill:#333}#mermaid-svg-cE5iQzO0yoEdIZFg .sectionTitle{text-anchor:start;font-size:11px;text-height:14px;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-cE5iQzO0yoEdIZFg .grid .tick{stroke:#d3d3d3;opacity:0.8;shape-rendering:crispEdges}#mermaid-svg-cE5iQzO0yoEdIZFg .grid .tick text{font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-cE5iQzO0yoEdIZFg .grid path{stroke-width:0}#mermaid-svg-cE5iQzO0yoEdIZFg .today{fill:none;stroke:red;stroke-width:2px}#mermaid-svg-cE5iQzO0yoEdIZFg .task{stroke-width:2}#mermaid-svg-cE5iQzO0yoEdIZFg .taskText{text-anchor:middle;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-cE5iQzO0yoEdIZFg .taskText:not([font-size]){font-size:11px}#mermaid-svg-cE5iQzO0yoEdIZFg .taskTextOutsideRight{fill:#000;text-anchor:start;font-size:11px;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-cE5iQzO0yoEdIZFg .taskTextOutsideLeft{fill:#000;text-anchor:end;font-size:11px}#mermaid-svg-cE5iQzO0yoEdIZFg .task.clickable{cursor:pointer}#mermaid-svg-cE5iQzO0yoEdIZFg .taskText.clickable{cursor:pointer;fill:#003163 !important;font-weight:bold}#mermaid-svg-cE5iQzO0yoEdIZFg .taskTextOutsideLeft.clickable{cursor:pointer;fill:#003163 !important;font-weight:bold}#mermaid-svg-cE5iQzO0yoEdIZFg .taskTextOutsideRight.clickable{cursor:pointer;fill:#003163 !important;font-weight:bold}#mermaid-svg-cE5iQzO0yoEdIZFg .taskText0,#mermaid-svg-cE5iQzO0yoEdIZFg .taskText1,#mermaid-svg-cE5iQzO0yoEdIZFg .taskText2,#mermaid-svg-cE5iQzO0yoEdIZFg .taskText3{fill:#fff}#mermaid-svg-cE5iQzO0yoEdIZFg .task0,#mermaid-svg-cE5iQzO0yoEdIZFg .task1,#mermaid-svg-cE5iQzO0yoEdIZFg .task2,#mermaid-svg-cE5iQzO0yoEdIZFg .task3{fill:#8a90dd;stroke:#534fbc}#mermaid-svg-cE5iQzO0yoEdIZFg .taskTextOutside0,#mermaid-svg-cE5iQzO0yoEdIZFg .taskTextOutside2{fill:#000}#mermaid-svg-cE5iQzO0yoEdIZFg .taskTextOutside1,#mermaid-svg-cE5iQzO0yoEdIZFg .taskTextOutside3{fill:#000}#mermaid-svg-cE5iQzO0yoEdIZFg .active0,#mermaid-svg-cE5iQzO0yoEdIZFg .active1,#mermaid-svg-cE5iQzO0yoEdIZFg .active2,#mermaid-svg-cE5iQzO0yoEdIZFg .active3{fill:#bfc7ff;stroke:#534fbc}#mermaid-svg-cE5iQzO0yoEdIZFg .activeText0,#mermaid-svg-cE5iQzO0yoEdIZFg .activeText1,#mermaid-svg-cE5iQzO0yoEdIZFg .activeText2,#mermaid-svg-cE5iQzO0yoEdIZFg .activeText3{fill:#000 !important}#mermaid-svg-cE5iQzO0yoEdIZFg .done0,#mermaid-svg-cE5iQzO0yoEdIZFg .done1,#mermaid-svg-cE5iQzO0yoEdIZFg .done2,#mermaid-svg-cE5iQzO0yoEdIZFg .done3{stroke:grey;fill:#d3d3d3;stroke-width:2}#mermaid-svg-cE5iQzO0yoEdIZFg .doneText0,#mermaid-svg-cE5iQzO0yoEdIZFg .doneText1,#mermaid-svg-cE5iQzO0yoEdIZFg .doneText2,#mermaid-svg-cE5iQzO0yoEdIZFg .doneText3{fill:#000 !important}#mermaid-svg-cE5iQzO0yoEdIZFg .crit0,#mermaid-svg-cE5iQzO0yoEdIZFg .crit1,#mermaid-svg-cE5iQzO0yoEdIZFg .crit2,#mermaid-svg-cE5iQzO0yoEdIZFg .crit3{stroke:#f88;fill:red;stroke-width:2}#mermaid-svg-cE5iQzO0yoEdIZFg .activeCrit0,#mermaid-svg-cE5iQzO0yoEdIZFg .activeCrit1,#mermaid-svg-cE5iQzO0yoEdIZFg .activeCrit2,#mermaid-svg-cE5iQzO0yoEdIZFg .activeCrit3{stroke:#f88;fill:#bfc7ff;stroke-width:2}#mermaid-svg-cE5iQzO0yoEdIZFg .doneCrit0,#mermaid-svg-cE5iQzO0yoEdIZFg .doneCrit1,#mermaid-svg-cE5iQzO0yoEdIZFg .doneCrit2,#mermaid-svg-cE5iQzO0yoEdIZFg .doneCrit3{stroke:#f88;fill:#d3d3d3;stroke-width:2;cursor:pointer;shape-rendering:crispEdges}#mermaid-svg-cE5iQzO0yoEdIZFg .milestone{transform:rotate(45deg) scale(0.8, 0.8)}#mermaid-svg-cE5iQzO0yoEdIZFg .milestoneText{font-style:italic}#mermaid-svg-cE5iQzO0yoEdIZFg .doneCritText0,#mermaid-svg-cE5iQzO0yoEdIZFg .doneCritText1,#mermaid-svg-cE5iQzO0yoEdIZFg .doneCritText2,#mermaid-svg-cE5iQzO0yoEdIZFg .doneCritText3{fill:#000 !important}#mermaid-svg-cE5iQzO0yoEdIZFg .activeCritText0,#mermaid-svg-cE5iQzO0yoEdIZFg .activeCritText1,#mermaid-svg-cE5iQzO0yoEdIZFg .activeCritText2,#mermaid-svg-cE5iQzO0yoEdIZFg .activeCritText3{fill:#000 !important}#mermaid-svg-cE5iQzO0yoEdIZFg .titleText{text-anchor:middle;font-size:18px;fill:#000;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-cE5iQzO0yoEdIZFg g.classGroup text{fill:#9370db;stroke:none;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family);font-size:10px}#mermaid-svg-cE5iQzO0yoEdIZFg g.classGroup text .title{font-weight:bolder}#mermaid-svg-cE5iQzO0yoEdIZFg g.clickable{cursor:pointer}#mermaid-svg-cE5iQzO0yoEdIZFg g.classGroup rect{fill:#ECECFF;stroke:#9370db}#mermaid-svg-cE5iQzO0yoEdIZFg g.classGroup line{stroke:#9370db;stroke-width:1}#mermaid-svg-cE5iQzO0yoEdIZFg .classLabel .box{stroke:none;stroke-width:0;fill:#ECECFF;opacity:0.5}#mermaid-svg-cE5iQzO0yoEdIZFg .classLabel .label{fill:#9370db;font-size:10px}#mermaid-svg-cE5iQzO0yoEdIZFg .relation{stroke:#9370db;stroke-width:1;fill:none}#mermaid-svg-cE5iQzO0yoEdIZFg .dashed-line{stroke-dasharray:3}#mermaid-svg-cE5iQzO0yoEdIZFg #compositionStart{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-cE5iQzO0yoEdIZFg #compositionEnd{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-cE5iQzO0yoEdIZFg #aggregationStart{fill:#ECECFF;stroke:#9370db;stroke-width:1}#mermaid-svg-cE5iQzO0yoEdIZFg #aggregationEnd{fill:#ECECFF;stroke:#9370db;stroke-width:1}#mermaid-svg-cE5iQzO0yoEdIZFg #dependencyStart{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-cE5iQzO0yoEdIZFg #dependencyEnd{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-cE5iQzO0yoEdIZFg #extensionStart{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-cE5iQzO0yoEdIZFg #extensionEnd{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-cE5iQzO0yoEdIZFg .commit-id,#mermaid-svg-cE5iQzO0yoEdIZFg .commit-msg,#mermaid-svg-cE5iQzO0yoEdIZFg .branch-label{fill:lightgrey;color:lightgrey;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-cE5iQzO0yoEdIZFg .pieTitleText{text-anchor:middle;font-size:25px;fill:#000;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-cE5iQzO0yoEdIZFg .slice{font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-cE5iQzO0yoEdIZFg g.stateGroup text{fill:#9370db;stroke:none;font-size:10px;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-cE5iQzO0yoEdIZFg g.stateGroup text{fill:#9370db;fill:#333;stroke:none;font-size:10px}#mermaid-svg-cE5iQzO0yoEdIZFg g.statediagram-cluster .cluster-label text{fill:#333}#mermaid-svg-cE5iQzO0yoEdIZFg g.stateGroup .state-title{font-weight:bolder;fill:#000}#mermaid-svg-cE5iQzO0yoEdIZFg g.stateGroup rect{fill:#ECECFF;stroke:#9370db}#mermaid-svg-cE5iQzO0yoEdIZFg g.stateGroup line{stroke:#9370db;stroke-width:1}#mermaid-svg-cE5iQzO0yoEdIZFg .transition{stroke:#9370db;stroke-width:1;fill:none}#mermaid-svg-cE5iQzO0yoEdIZFg .stateGroup .composit{fill:white;border-bottom:1px}#mermaid-svg-cE5iQzO0yoEdIZFg .stateGroup .alt-composit{fill:#e0e0e0;border-bottom:1px}#mermaid-svg-cE5iQzO0yoEdIZFg .state-note{stroke:#aa3;fill:#fff5ad}#mermaid-svg-cE5iQzO0yoEdIZFg .state-note text{fill:black;stroke:none;font-size:10px}#mermaid-svg-cE5iQzO0yoEdIZFg .stateLabel .box{stroke:none;stroke-width:0;fill:#ECECFF;opacity:0.7}#mermaid-svg-cE5iQzO0yoEdIZFg .edgeLabel text{fill:#333}#mermaid-svg-cE5iQzO0yoEdIZFg .stateLabel text{fill:#000;font-size:10px;font-weight:bold;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-cE5iQzO0yoEdIZFg .node circle.state-start{fill:black;stroke:black}#mermaid-svg-cE5iQzO0yoEdIZFg .node circle.state-end{fill:black;stroke:white;stroke-width:1.5}#mermaid-svg-cE5iQzO0yoEdIZFg #statediagram-barbEnd{fill:#9370db}#mermaid-svg-cE5iQzO0yoEdIZFg .statediagram-cluster rect{fill:#ECECFF;stroke:#9370db;stroke-width:1px}#mermaid-svg-cE5iQzO0yoEdIZFg .statediagram-cluster rect.outer{rx:5px;ry:5px}#mermaid-svg-cE5iQzO0yoEdIZFg .statediagram-state .divider{stroke:#9370db}#mermaid-svg-cE5iQzO0yoEdIZFg .statediagram-state .title-state{rx:5px;ry:5px}#mermaid-svg-cE5iQzO0yoEdIZFg .statediagram-cluster.statediagram-cluster .inner{fill:white}#mermaid-svg-cE5iQzO0yoEdIZFg .statediagram-cluster.statediagram-cluster-alt .inner{fill:#e0e0e0}#mermaid-svg-cE5iQzO0yoEdIZFg .statediagram-cluster .inner{rx:0;ry:0}#mermaid-svg-cE5iQzO0yoEdIZFg .statediagram-state rect.basic{rx:5px;ry:5px}#mermaid-svg-cE5iQzO0yoEdIZFg .statediagram-state rect.divider{stroke-dasharray:10,10;fill:#efefef}#mermaid-svg-cE5iQzO0yoEdIZFg .note-edge{stroke-dasharray:5}#mermaid-svg-cE5iQzO0yoEdIZFg .statediagram-note rect{fill:#fff5ad;stroke:#aa3;stroke-width:1px;rx:0;ry:0}:root{--mermaid-font-family: '"trebuchet ms", verdana, arial';--mermaid-font-family: "Comic Sans MS", "Comic Sans", cursive}#mermaid-svg-cE5iQzO0yoEdIZFg .error-icon{fill:#522}#mermaid-svg-cE5iQzO0yoEdIZFg .error-text{fill:#522;stroke:#522}#mermaid-svg-cE5iQzO0yoEdIZFg .edge-thickness-normal{stroke-width:2px}#mermaid-svg-cE5iQzO0yoEdIZFg .edge-thickness-thick{stroke-width:3.5px}#mermaid-svg-cE5iQzO0yoEdIZFg .edge-pattern-solid{stroke-dasharray:0}#mermaid-svg-cE5iQzO0yoEdIZFg .edge-pattern-dashed{stroke-dasharray:3}#mermaid-svg-cE5iQzO0yoEdIZFg .edge-pattern-dotted{stroke-dasharray:2}#mermaid-svg-cE5iQzO0yoEdIZFg .marker{fill:#333}#mermaid-svg-cE5iQzO0yoEdIZFg .marker.cross{stroke:#333}:root { --mermaid-font-family: "trebuchet ms", verdana, arial;}#mermaid-svg-cE5iQzO0yoEdIZFg {color: rgba(0, 0, 0, 0.75);font: ;}

建立连接数据库获取数据
flask为每个问题创建路由
创建HTML模板进行页面整体布局
将数据转换成需要的格式
使用flask返回json数据
为每个块编写JS文件
单独写一个JS文件用Ajax获取数据上传到对应JS文件
进行调试

准备工作:

因为前边数据分析篇的分析后建表的考虑不周,可视化用到了两个新的表,就把新表的生成过程写在这里吧,用到了hive,MySQL,sqoop:

1.双十二当天top10的用户信息(包括:useid,购买数量,省份)

MySQL建表:

MySQL>create table fx_5 (user_id int(10),b_count int(12),province varchar(12));

hive建表:

hive>create table fx_5 (user_id int,b_count int,province string) row format delimited fields terminated by ',';

分析存储:

hive>insert into table fx_5>select user_id,count(behavior_type) count,province>from small_user_out>where time='2014-12-12' and behavior_type=4>group by user_id,behavior_type,province>order by count desc>limit 10;

hive导入MySQL:

sqoop export --connect jdbc:mysql://localhost:3306/hive --username hive -password 123123 --table fx_5 --export-dir hdfs://master-slave:8020/user/hive/warehouse/hive.db/fx_5 --input-fields-terminated-by ','

2.每天的购买率
MySQL建表:

mysql>create table fx_6 (time data,month int(8),day int(8),v_count int,b_count int,b_u double);

hive建表:

create table fx_6 (time date,month int,day int,v_count int,b_count int,b_all double) row format delimited fields terminated by ',';

分析存储:

hive>insert into table fx_6>select time,month(time),>day(time),>sum(case behavior_type when 1 then 1 else 0 end),>sum(case behavior_type when 4 then 1 else 0 end),>sum(case behavior_type when 4 then 1 else 0 end)/sum(case when behavior_type=1 then 1 when behavior_type=2 then 1 when behavior_type=3 then 1 when behavior_type=4 then 1 else 0 end)>from small_user_out>group by time;

hive导入MySQL:

sqoop export --connect jdbc:mysql://localhost:3306/hive --username hive -password 123123 --table fx_6 --export-dir hdfs://master-slave:8020/user/hive/warehouse/hive.db/fx_6 --input-fields-terminated-by ','

一、创建项目:

使用PyCharm创建一个Flask项目,如果是专业版的PyCharm自带的有Flask模板,直接创建即可。直接使用Flask模板创建的Flask项目里边会有已经自动生成的static目录,templates模板目录以及一个app.py文件,文件里也有一些简单的代码,运行可生成一个简单的web页面。如果不是专业版的,这些内容都可以手动创建。

二、建立数据库连接获取数据:

创建工具python文件utils,引入pymysql库,编写连接数据库的函数,获取查询到的数据的函数以及关闭连接的函数,方便后边使用的时候可以直接调用utils里封装的函数。

import pymysql// 创建连接
def get_conn():conn = pymysql.connect(host="192.168.172.140", // 连接数据库的IP地址port=3306,user="root",            //连接数据库的用户名password="123123",      //密码db="hive",              //连接的数据库charset="utf8")cursor = conn.cursor()return conn,cursor// 关闭连接
def close_conn(conn, cursor):cursor.close()conn.close()// 获取查询结果
def query(sql):conn, cursor = get_conn()cursor.execute(sql)res = cursor.fetchall()close_conn(conn, cursor)return res

数据库连接成功后,接下来我们要做的是获取每个问题所需要的数据,针对每个问题定义不同的函数和SQL语句(同样写在utils里):

// 获取问题一的数据
def get_q1_data():sql = "select day,b_count,v_count " \"from fx_6 " \"where month=11 " \"order by day;"res = query(sql)print("q1 Query the database successfully")return res// 获取问题二的数据
def get_q2_data():sql = "select day,b_count,v_count " \"from fx_6 " \"where month=12 " \"order by day;"res = query(sql)print("q2 Query the database successfully")return res// 获取问题三的数据
def get_q3_data():sql = "select province,buy_count " \"from fx_3;"res = query(sql)print("q3 Query the database successfully")return res//获取问题四的数据
def get_q4_data():sql = "select * " \"from fx_5 " \"order by b_count desc;"res = query(sql)print("q1 Query the database successfully")return res//获取问题五的数据
def get_q5_data():sql = "select date_format(time,'%m-%d') as time,b_u " \"from fx_6; " \res = query(sql)print("q5 Query the database successfully")return res

至此,连接数据库以及获取数据的函数已经定义完成,后边需要只需调用即可。

三、页面布局:

我将问题中的,每天的浏览量和购买量拆分成了十一月的浏览量和购买量和十二月的浏览量和购买量,所以四个问题变成了五个问题即:

  • Q1:十一月的浏览量和购买量
  • Q2:十二月的浏览量和购买量
  • Q3:双十二当天的各个省的发货量
  • Q4:双十二当天top10的用户信息(包括:useid,购买数量,省份)
  • Q5:每天的购买率

我的计划是Q1,Q2柱状图,Q3在地图上显示,Q4列表,Q5折线图

我的页面的布局:

先在templates目录下创建我们的模板页面:


Python不是专业的HTML编写工具,建议使用别的工具操作方便,我用的VScode,对页面进行布局:

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title>
</head>
<body><div id="title">用户消费行为分析</div><div id="q1">十一月的浏览量和购买量</div><div id="q2">十二月的浏览量和购买量</div><div id="q3">双十二当天的各个省的发货量</div><div id="q4">双十二当天top10的用户信息(包括:useid,购买数量,省份)</div><div id="q5">每天的购买率</div>
</body>
</html>

为了使代码看起来更简单舒服,在static目录下新创建一个CSS目录,并在该目录下创建一个css文件用来存放main模板的样式。使用absolute绝对定位划分板块,并连接到模板文件上。

#title {position: absolute;width: 100%;height: 14%;top: 0;left: 0;font-size: 45px;font-weight:bold;display: flex;align-items: center;justify-content: center;
}
#q1 {position: absolute;width: 30%;height: 43%;top: 14%;left: 0;background: rgba(36, 94, 86, 0.692);
}
#q2 {position: absolute;width: 30%;height: 43%;top: 57%;left: 0;background: rgba(11, 74, 116, 0.603);
}
#q3 {position: absolute;width: 40%;height: 86%;top: 14%;left: 30%;background: rgba(15, 17, 128, 0.479);
}
#q4 {position: absolute;width: 30%;height: 43%;top: 14%;left: 70%;background: rgba(165, 31, 192, 0.411);
}
#q5 {position: absolute;width: 30%;height: 43%;top: 57%;left: 70%;background: rgba(107, 9, 78, 0.493);
}

在head之间添加代码来引入css文件。

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

效果展示:

四、下载ECharts、jQuery等JS库文件:

ECharts和jQuery都可去官网下载,同时因为我计划的是使用中国地图实现问题三的可视化,所以还需要一个中国地图的ECharts文件:
下载echarts.min.js即可:ECharts下载地址
选择一个版本下载即可:jQuery下载地址
针对问题三我们需要引入一个中国地图的js文件:china.js下载地址

五、在官网找到需要的模板并为每个问题编写JS文件:

在static目录下建立js目录存放js文件包括echarts,jQuery等所有js文件
我们给每个问题单独创建一个JS文件,可以更加清晰的找到代码使用,后边调试也更加方便。
前两个问题都是柱状图,在Echarts官网找个模板:
官方也有5分钟上手ECharts等教程,没用过的可以体验一下,不算太难。下边我使用的模板是根据官方实例进行修改后的代码,自己使用的时候可以根据个人喜好进行调整等。
链接:ECharts官网实例页面

5.1 创建问题一JS文件命名为ec_left_1.js

// 问题1 echarts代码// 基于准备好的dom,初始化echarts实例
var ec_left_1 = echarts.init(document.getElementById('q1'),'white');var ec_left_1_option = {   title: {                               // 图标标题设置text: '2014年11月日浏览量和购买量',  x: 'center',bottom:10},legend: {                                // 图例设置data: ['购买数量','浏览数'],top:10},toolbox: {                              // 工具栏设置top:10,feature: {magicType: {type: ['stack', 'tiled']},dataView: {},saveAsImage: {pixelRatio: 2}}},tooltip: {},                         // 提示框设置xAxis: [{                               // 横坐标,这里加了个[]方便Ajax传入数据data: [],}],yAxis: [{                                }],series: [{                               // 系列列表name: '购买数量',type: 'bar',data: [],barMaxWidth:"50%"},{name:'浏览数',type:'bar',data: [],barMaxWidth:"50%"}]
};
ec_left_1.setOption(ec_left_1_option)       // 使用刚指定的配置项和数据显示图表

5.2 创建问题二JS文件命名为ec_left_2.js

因为问题一个问题二只是月份不一样,所以代码基本可以使用相同的

// 问题2 echarts代码var ec_left_2 = echarts.init(document.getElementById('q2'),'white');
var ec_left_2_option = {   title: {text: '2014年12月日浏览量和购买量',x: 'center',bottom:10},legend: {data: ['购买数量','浏览数'],top:10},toolbox: {top:10,feature: {magicType: {type: ['stack', 'tiled']},dataView: {},saveAsImage: {pixelRatio: 2}}},tooltip: {},xAxis: [{data: [],}],yAxis: [{}],series: [{name: '购买数量',type: 'bar',data: [],barMaxWidth:"50%"},{name:'浏览数',type:'bar',data: [],barMaxWidth:"50%"}]
};
ec_left_2.setOption(ec_left_2_option)

5.3 创建问题三JS文件命名为ec_center.js

问题三注意数据的格式,我们可以先把mydata的数据传入,打开页面查看是否可以正常显示

// 问题3 echarts代码var ec_center = echarts.init(document.getElementById('q3'),'white');var mydata = [{'name':'河南','value':123},{'name':'湖南','value':321}]var ec_center_option = {title:{text:'2014-12-12 全国各地销量一览',textStyle:{fontSize:25},subtext:'',left:'center',y:'',top:50,},tooltip:{trigger:'item'},visualMap: {                                    // 小导航图标min:0,max:25,left:"40%",bottom:60,text:['high','low'],calculable:true,orient: 'horizontal',inRange:{color:['yellow', 'orangered','red']}},series: [{                                      //配置属性name: '购买人数',type: 'map',mapType: 'china',roam: false,                              //拖动和缩放itemStyle: {normal: {borderWidth: .5,                    //区域边框宽度borderColor: '#009fe8',           //区域边框颜色areaColor: "#ffefd5",                 //区域颜色},emphasis: {                             //鼠标滑过地图高亮的相关设置borderWidth: .5,borderColor: '#4b0082',areaColor: "#fff",}},label: {normal: {show: true,                         //省份名称fontSize: 10,},emphasis: {show: true,fontSize: 12,}},data:[] //mydata //数据}]
};
ec_center.setOption(ec_center_option)

5.4 创建问题四JS文件命名为ec_right_1.js

问题四是表格,而不是使用ECharts。因为JS的内容我不怎懂,这里的表格生成代码不是我写的,而是我的一个很好的朋友最近在学JS发给我用的,然而我用的并不好。当我好不容易勉强看懂怎么使用以及一点原理后,在我使用时发现Ajax从后端获取到的数据到前端顺序不一样了,这个顺序是我无法控制的,网上找方法也没有头绪。无奈,只好从数据库查询数据后,先把数据写死了,这也就是我前边说做的不完美的原因。有缘人看到解决了可以告诉我,或者有别的什么办法也可以评论一下。我也打算去深入学一些JS的内容来尝试自己做一下会不会更可控一点。

// 问题4生成表格(function ($) {// 给 $ 的原型添加方法$.fn.table = function (arrTableHead, arrTableBody) {// this 是调用table方法的 jQ 对象// arrTableHead, arrTableBody 分别生成表头和主体var list = [];list.push('<table>')// 生成表头list.push('<thead>');list.push('<tr>');for (var i = 0; i < arrTableHead.length; i++) {list.push('<th>');list.push(arrTableHead[i]);list.push('</th>');}list.push('</tr>');list.push('</thead>');// 生成主体list.push('<tbody>');for (var i = 0; i < arrTableBody.length; i++) {list.push('<tr>');for (var key in arrTableBody[i]) {list.push('<td>');list.push(arrTableBody[i][key]);list.push('</td>');}list.push('</tr>');}list.push('</tbody>');list.push('</table>');console.log(list.join(""));// 把list里面的内容拼接成字符串this.html(list.join(""));}
}(jQuery));
var a_h = ['top','user_id','购买数量','城市']
var a_b = [{'top': 1, 'id': 103794013, 'count': 3, 'city': '浙江'}, {'top': 2, 'id': 103794013, 'count': 3, 'city': '江西'}, {'top': 3, 'id': 101490976, 'count': 3, 'city': '广东'}, {'top': 4, 'id': 102650143, 'count': 3, 'city': '云南'}, {'top': 5, 'id': 10095384, 'count': 3, 'city': '甘肃'}, {'top': 6, 'id': 101686429, 'count': 2, 'city': '安徽'}, {'top': 7, 'id': 101490976, 'count': 2, 'city': '西藏'}, {'top': 8, 'id': 103995979, 'count': 2, 'city': '内蒙古'}, {'top': 9, 'id': 101847145, 'count': 2, 'city': '福建'}, {'top': 10, 'id': 103995979, 'count': 2, 'city': '湖北'}]
function handle(){console.log(typeof a_h)console.log(a_b)$('#c').table(a_h,a_b);
}
$('#c').table(a_h,a_b);

5.5 创建问题五JS文件命名为ec_right_2.js

问题五是一个折线图,直接使用的最简单的例子

// 问题5 echarts代码var ec_right_2 = echarts.init(document.getElementById('q5'),'white');
var ec_right_2_option = {title:{text:'每日购买率',left:'center',bottom:10},tooltip:{},xAxis: [{type: 'category',data: []}],yAxis: {type: 'value'},series: [{name:"购买率",data: [],type: 'line'}]
};
ec_right_2.setOption(ec_right_2_option)

5.6 去模板文件里建立JS文件的连接

建立连接并对模板文件和CSS文件进行修改将页面调整成自己想要的样子
HTML:

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><!-- 以下三行代码用来定义强制从服务器获取新页面,不设置可能会造成页面数据不能及时更新 --><meta http-equiv="Pragma" content="no-cache"><meta http-equiv="Cache-Control" content="no-cache"><meta http-equiv="Expires"  content="0"><title>用户消费行为分析</title><link rel="stylesheet" href="../static/css/main.css"><script src="../static/js/jquery-3.5.1.js"></script><script src="../static/js/echarts.min.js"></script><script src="../static/js/china.js"></script>
</head>
<body><div id="gyroContain"><div id="title">用户消费行为分析</div><div id="q1"></div><div id="q2"></div><div id="q3"></div><div id="q4"><div id="table"><!-- 双十二当天top10的用户信息(包括:useid,购买数量,省份) --><table border="1" id="c"></table></div></div><div id="q5"></div></div>
</body>
</html>
<script src="../static/js/ec_center.js"></script>
<script src="../static/js/ec_left_1.js"></script>
<script src="../static/js/ec_left_2.js"></script>
<script src="../static/js/ec_right_1.js"></script>
<script src="../static/js/ec_rigth_2.js"></script>

CSS:

html, body {height:100%;overflow:auto;margin: 0;}  /* 防止页面抖动 */
html{overflow-y:scroll;}
#title {position: absolute;width: 100%;height: 14%;top: 0;left: 0;font-size: 45px;font-weight:bold;display: flex;align-items: center;justify-content: center;
}
#q1 {position: absolute;width: 30%;height: 43%;top: 14%;left: 0;background: white;
}
#q2 {position: absolute;width: 30%;height: 43%;top: 57%;left: 0;background: white;
}
#q3 {position: absolute;width: 40%;height: 86%;top: 14%;left: 30%;background: white;
}
#q4 {position: absolute;width: 30%;height: 43%;top: 14%;left: 70%;background: white;
}
#q5 {position: absolute;width: 30%;height: 43%;top: 57%;left: 70%;background: white;
}table{width: 80%;border: 1px solid #3F3F3F; padding: 5px;margin: 14px auto;            border-collapse: collapse;
}
th{ border: 1px solid #3F3F3F; background-color: #3F3F3F;color: #fff;padding: 3px 10px;
}
td{ border: 1px solid #3F3F3F; padding: 3px 10px; font-size: 16px; text-align: center;
}

此时打开HTML页面视图应该是:

这个时候,我们可以在所有问题所对应的JS文件里自定义一些数据,这样看是否可以成功显示,是否达到预期效果,并记住需要的数据格式应该是什么。如果没有再做调整,如果达到了便可开始下一步。

六、使用Flask创建路由,并把数据处理成需要的格式:

首先我们需要使用render_template,将我们做好的模板引入:

from flask import render_template   # 导入Flask引入模板的模块
import utils                        # 引入自己编写的工具模块,方便调用获取数据
from flask import jsonify           # 导入Flask的jsonify方便返回json数据@app.route('/')
def template():return render_template("main.html")

其次我们需要知道每个数据所需要的格式

6.1 问题一、二的路由创建以及数据格式转换

Q1、Q2:柱状图,我们需要的数据是Day、浏览量和购买量。
Day对应的是xAxis数据,浏览量和购买量对应的是两个data数据,数据库查询返回的数据格式是:


((day,购买量,浏览量),(day2,购买量2,浏览量2))
我们需要的数据是在列表里的因此我们需要把数据的格式转换成需要的格式:

# 定义问题一的路由以及数据格式处理
@app.route('/q1')
def get_q1_data():data = utils.get_q1_data()day,b_count,v_count = [],[],[]for a,b,c in data[:]:day.append(int(a))b_count.append(b)v_count.append(c)print(day)print(b_count)print(v_count)return jsonify({"day_11": day, "b_count_11": b_count, "v_count_11": v_count})# 定义问题二的路由以及数据格式处理
@app.route('/q2')
def get_q2_data():data = utils.get_q2_data()day,b_count,v_count = [],[],[]for a,b,c in data[:]:day.append(int(a))b_count.append(b)v_count.append(c)print(day)print(b_count)print(v_count)return jsonify({"day_12": day, "b_count_12": b_count, "v_count_12": v_count})

6.2 问题三的路由创建以及数据格式转换

问题三我们是使用中国地图展示的,从前边创建的JS文件我们可以得知问题三需要的数据格式为:

[{‘name’:‘河南’,‘value’:123},{‘name’:‘湖南’,‘value’:321}]

而我们直接从数据库获取的数据格式为:

我们需要的是一种类似与字典的格式:

# 定义问题三的路由以及数据格式处理
@app.route('/q3')
def get_q3_data():lis = []for tup in utils.get_q3_data():lis.append({"name":tup[0],"value":int(tup[1])})return jsonify({"data":lis})

6.3 问题四的路由创建以及数据格式转换

问题四前边已经说了问题,这里就先把有问题的代码写上吧,不做阐述:

# 定义问题四的路由以及数据格式处理
@app.route('/q4')
def get_q4_data():lis = []i = 0for tup in utils.get_q4_data():i += 1lis.append({"top":i,"id":tup[0],"count":int(tup[1]),"city":tup[2]})print(lis)return jsonify(lis)

6.4 问题五的路由创建以及数据格式转换

Q5是折线图,类似与柱状图,需要的数据格式也基本和柱状图一样,直接从数据库获取的数据格式为:

路由创建及格式整理:

# 定义问题五的路由以及数据格式处理
@app.route('/q5')
def get_q5_data():data = utils.get_q5_data()time,b_u = [],[]for a,b in data[:]:time.append(a)b_u.append(b)print(time)print(b_u)return jsonify({"time": time, "b_u": b_u})

使用Flask创建路由,并把数据处理成需要的格式已经做完,接下来我们只要从前端获取数据并上传上去,我们的这个可视化大屏基本就算完成了。

七、编写Ajax获取数据传给对应问题的JS文件:

我们单独写一个命名为control的JS文件(命名随意,自己决定无特殊要求),在这个文件下我们把每个问题获取数据的Ajax代码分别封装成五个函数,再进行调用,这样就算后期要做动态可视化大屏,我们直接添加一个定时刷新新就可以了。

// Ajax获取每个问题的数据function get_q1_data(){$.ajax({url:"/q1",success:function(data){ec_left_1_option.xAxis[0].data=data.day_11ec_left_1_option.series[0].data=data.b_count_11ec_left_1_option.series[1].data=data.v_count_11ec_left_1.setOption(ec_left_1_option)},error:function(xhr,type,errorThrown){alert("图表1请求数据失败!");}})
}function get_q2_data(){$.ajax({url:"/q2",success:function(data){ec_left_2_option.xAxis[0].data=data.day_12ec_left_2_option.series[0].data=data.b_count_12ec_left_2_option.series[1].data=data.v_count_12ec_left_2.setOption(ec_left_2_option)},error:function(xhr,type,errorThrown){alert("图表2请求数据失败!");}})
}function get_q3_data(){$.ajax({url:"/q3",success:function(data){ec_center_option.series[0].data=data.dataec_center.setOption(ec_center_option)},error:function(xhr,type,errorThrown){alert("图表3请求数据失败!");}})
}// function get_q4_data(){//     $.ajax({//         url:"/q4",
//         success:function(data){//             a_b=data
//             console.log(typeof a_b)
//             console.log(a_b)
//             alert(a_b)
//         },error:function(xhr,type,errorThrown){//             alert("表格获取数据失败")
//         }
//     })
// }function get_q5_data(){$.ajax({url:"/q5",success:function(data){ec_right_2_option.xAxis[0].data=data.timeec_right_2_option.series[0].data=data.b_uec_right_2.setOption(ec_right_2_option)},error:function(xhr,type,errorThrown){alert("图表5请求数据失败!");}})
}get_q1_data()
get_q2_data()
get_q3_data()
// get_q4_data()
get_q5_data()

八、运行调试:

这个项目到这里就结束了,我们直接在PyCharm运行app.py文件,查看是否可以正常运行,如果不可以可能是某个地方出错了。具体的排查方法因出现问题的不同而异,你可以在后端的PyCharm单独建立一个test文件用来测试后端的数据获取等步骤是否可以正常执行;同时你也可以在前端直接在网页上按F12查看里边的Console查看前端代码是否有问题。还可以评论,私聊我们一起探讨学习。

九、总结:

结果展示:

Flask、Ajax、JS、ECharts这些东西算是第一次接触,搞了好久才把这个可视化做完。在使用这些工具的时候大多磕磕绊绊且需要摸索好久,中间也是错误频出,最后虽然结束却不完美,仍需继续努力学习。这次培训真的学了不少东西吧,重要的是发现自己真的菜,啥都不会,学的还慢。至此历经一个月多一点终于把这个案例完整做完,暑假也接近尾声,开学之后要加倍努力了,希望可以越来越好且学到的东西越来越精。


另外我把这个项目的源码也传到了GitHub上,还没用过不太会,上传应该没出错,大家有需要可以自行去下载,里边包括这个项目的源数据以及我处理过的数据:

GitHub源码链接

数据可视化:利用Python和Echarts制作“用户消费行为分析”可视化大屏相关推荐

  1. 利用python爬取猫眼电影,分析《大侦探皮卡丘》|凹凸数读

    利用python爬取猫眼电影,分析<大侦探皮卡丘>,看看当皮卡丘长出绒毛,"丑拒"还是"真香"都在猫眼短评里了. 本文首发于微信公众号<凹凸数 ...

  2. Python网络爬虫爬取招聘数据(利用python简单零基础)可做可视化

    爬取Boss直聘相关的招聘数据 一.相关需求分析 1.目的 二.直聘网页结构分析 1.网页相关值的查找 2.网页的下一页规律查找 三.Python相关的第三库介绍 1.Urllib的介绍 (1)url ...

  3. 数据分析项目:用户消费行为分析

    用户消费行为分析实战 利用pandas进行数据处理,分析用户消费行为. 数据来源CDNow网站的用户购买明细,一共有用户ID,购买日期,购买数量,购买金额四个字段. 1.导入常用需要的库 # 导入常用 ...

  4. 1【源码】数据可视化:基于 Echarts +Java SpringBoot 实现的动态实时大屏范例-互联网企业数据分析

    目录 效果展示 1.首先看动态效果图 2.再看实时分片数据图 一. 需求确认 1.确定产品上线部署的屏幕LED分辨率 2.功能模块 3.部署方式 二.整体架构设计 三.开发环境搭建 1.Java开发环 ...

  5. 12【源码】数据可视化:基于 Echarts +Java SpringBoot 实现的动态实时大屏范例 - 供应链

    数据可视化大屏的出现,掀起一番又一番的浪潮,众多企业主纷纷想要打造属于自己的"酷炫吊炸天"的霸道总裁大屏驾驶舱. 之前有小伙伴们建议我出一些视频课程来学习Echarts,这样可以更 ...

  6. 2【源码】数据可视化:基于 Echarts + Java SpringBoot 实现的动态实时大屏范例-物流大数据

    数据可视化大屏的出现,掀起一番又一番的浪潮,众多企业纷纷想要打造属于自己的"酷炫吊炸天"的霸道总裁大屏驾驶舱. 之前小伙伴们建议我出一些视频课程来学习Echarts,这样可以更快上 ...

  7. 3【源码】数据可视化:基于 Echarts +Java SpringBoot 实现的动态实时大屏范例-物联网

    数据可视化大屏的出现,掀起一番又一番的浪潮,众多企业主纷纷想要打造属于自己的"酷炫吊炸天"的霸道总裁大屏驾驶舱. 之前有小伙伴们建议我出一些视频课程来学习Echarts,这样可以更 ...

  8. python处理行情数据_利用Python脚本来获取期货行情数据

    因为自己最近在学习做期货交易,想要下载期货的行情数据来做分析.有一些交易软件是可以导出数据的,但是导出的过程还是需要很多的手工操作,自己在想能不能通过Python程序来实现呢. 新浪期货数据接口介绍 ...

  9. 利用python做微信聊天记录词云分析——记录美好回忆

    目录 1 概述 2 数据准备 2.1 安卓设备 2.1.1 Root手机,安装Root Explorer 2.1.2 用Root Explorer将聊天记录的数据文件导出并存入电脑 2.1.3 对En ...

最新文章

  1. http请求过程简要
  2. 撤销 git commit
  3. MT6592 经验积累
  4. C语言嵌入系统编程修炼-性能优化
  5. 【codevs1073】家族,胡写并查集
  6. IS-IS详解(八)——深入探究IS-IS DIS选举机制
  7. Oracle中 如何用一个表的数据更新另一个表中的数据(含表备份)
  8. 婚姻是一堂需要认真学习的课程
  9. git 公钥提交代码_Git自由之章 - 关于SSH 公钥
  10. arduino学习系列——DHT11温湿度传感器的使用
  11. Python资源下载
  12. 震惊世人的10个Python黑科技,你知道几个?
  13. 电子面单平台JAVA对接方案
  14. 慧都科技:软件正版化不会一蹴而就 但趋势明显
  15. 使用vscode,根据vue基础模板文件生成代码
  16. php滚动公告栏,jQuery实现上下滚动公告栏详细代码
  17. HTML5树叶飘落动画
  18. Virus_JS3_PyAnalysisAndSummary
  19. 弹簧板(加强) - 计蒜客
  20. Mac端Charles抓包之后unkown的具体解决方案

热门文章

  1. matlab multiply,MATLAB Matrix Multiply Code效率
  2. ID/cpu/MI卡、非接触式读卡器资料集合
  3. 韩版机泛泰A850framework去除漫游、本地化
  4. GSM Channel Mode Modify和Channel Mode Modify Acknowledge信令
  5. 使用jcrop实现裁切图片
  6. Windows 消息大全
  7. android自定义起止时间的时间刻度尺,Android 自定义View篇(六)实现时钟表盘效果...
  8. Python经典编程习题100例:第20例:落体反弹问题
  9. 华为防火墙通用配置详解
  10. 5.2 PMBOK--收集需求