日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > 数据库 >内容正文

数据库

[py]access日志入mysql-通过flask前端展示

發(fā)布時間:2025/4/14 数据库 43 豆豆
生活随笔 收集整理的這篇文章主要介紹了 [py]access日志入mysql-通过flask前端展示 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

目錄

  • pymysql組裝sql入庫日志
  • 代碼組織
  • 將入庫的日志通過flask前端展示

pymysql組裝sql入庫日志

pymysql模塊的用法

采集這些指標(metirc)都是linux環(huán)境,會用到mysql,做為數(shù)據(jù)的存儲,我用docker來啟動

docker run \ -p 3306:3306 \ -v /data/mysql:/var/lib/mysql \ -v /etc/localtime:/etc/localtime \ --name mysql5 \ --restart=always \ -e MYSQL_ROOT_PASSWORD=123456 \ -d mysql:5.6.23 \ --character-set-server=utf8 \ --collation-server=utf8_general_ci create database mem; create table mem_used(used int, time int)- 時間格式 >>> import time >>> time.time() 1516860432.386474- 入庫后是整形,db自動處理, 也可以入庫前int(time). MySQL [mem]> select * from mem_used; +-----------+------------+ | used | time | +-----------+------------+ | 628658176 | 1516842082 | | 628813824 | 1516842083 | | 628936704 | 1516842084 | | 628936704 | 1516842085 | ...

一個用法實例, 獲取指標(通過psutil模塊直接獲取到已使用的內(nèi)存) 也可以自己算出.

import psutil import time import pymysql as mscon = ms.connect(host='127.0.0.1', user='root', passwd='123456', db='mem') con.autocommit(True) cur = con.cursor()while True:used = psutil.virtual_memory().usedsql = 'insert into mem_used values(%s,%s)' % (used / 1024 / 1024, int(time.time())) ## Mbcur.execute(sql)time.sleep(1)- %s可以接受任意類型的值

后面會將db操作封裝成模塊.

說下本次的任務

  • 本次的任務是將apache的access.log的(ip+狀態(tài))+出現(xiàn)次數(shù), 入庫到mysql里做分析. 分析網(wǎng)站訪問的top10
  • 日志樣式如下, 以空格分隔 arr[0] arr[8] 分別是ip和狀態(tài)碼
61.159.140.123 - - [23/Aug/2014:00:01:42 +0800] "GET /favicon.ico HTTP/1.1" 404 \ "-" "Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/29.0.1547.66 Safari/537.36 LBBROWSER" "-"
  • 通過pymysql模塊操作mysql數(shù)據(jù)庫

  • 將結果放在res={}一個大的字典里. 核心統(tǒng)計思路如下. 如果字典無key,則value初始化為1; 如果字典有key,則 以key對應的value +1

- 為何是這種格式,取決于echarts數(shù)據(jù)格式所需. 通常是找到一個合適的圖,對圖中數(shù)據(jù)胸有程序,即可以看到它需要一些什么數(shù)據(jù),在看下echarts代碼,看下需要什么格式的數(shù)據(jù), 然后后端組裝, json.dumps后返回.res[(ip, status)] = res.get((ip, status), 0) + 1
  • 對字典的值排序
- 遍歷日志文件,獲取到一個大的字典如下 res = {('182.145.101.123', '200'): 302, ('139.205.220.131', '404'): 1, ('119.146.75.13', '304'): 10, ('59.39.103.85', '200'): 56, ... }- 對字典排序 轉(zhuǎn)成 列表 后插入 print sorted(res.items(), key=lambda x: x[1], reverse=True)[(('123.174.51.164', '200'), 6930), (('117.63.146.40', '200'), 1457), (('118.112.143.148', '404'), 1336), (('111.85.34.165', '200'), 1325), ...]- 對排序后的列表(字典),字符串拼接sql,并插入數(shù)據(jù)庫 for i in sorted(res.items(), key=iambda x: x[1], reverse=True):sql = "insert into iog vaiues ('%s','%s','%s')" % (i[0][0], i[0][1], i[1])db.execute(sql)

代碼組織

入庫代碼

log2db.py

#!/usr/bin/env python # coding=utf-8from dbutils import DB# 連接mysql db = DB(host="127.0.0.1",user="root",passwd="",db="logtest" )# 日志處理成一個大的指定格式的字典(已統(tǒng)計好出現(xiàn)的次數(shù)) ((ip, status), count) res = {} with open('log.txt') as f:for line in f:if line == "\n":continuearr = line.split(" ")ip = arr[0]status = arr[8]res[(ip, status)] = res.get((ip, status), 0) + 1# 組合sql,執(zhí)行sql入庫日志 for l in sorted(res.items(), key=lambda x: x[1], reverse=True):# {('192.168.1.1',404): 1000,('192.168.1.1',403): 3000,('192.168.1.1',200): 2000,}sql = "insert into log values ('%s','%s','%s')" % (l[0][0], l[0][1], l[1])db.execute(sql)

dbutils.py

#!/usr/bin/env python # coding=utf-8import pymysql as msclass DB:def __init__(self, host, user, passwd, db):self.host = hostself.user = userself.passwd = passwdself.db = dbself.connect()def connect(self):self.conn = ms.connect(host=self.host,user=self.user,passwd=self.passwd,db=self.db)self.conn.autocommit(True)self.cursor = self.conn.cursor()def execute(self, sql):try:self.cursor.execute(sql)except Exception as e:self.cursor.close()self.conn.close()self.connect()return self.execute(sql)else:return self.cursor# def query(self,tables):# sql = 'select * from users'# self.cursor.execute(sql)# return self.cursor.fetchall()

下載實例日志: https://github.com/lannyMa/flask_info/blob/master/demo5/log.txt

執(zhí)行腳本入庫

python log2db.py

結果查看

入庫完成后, flask前端展示+echarts

將入庫的日志通過flask前端展示

難點是找圖形的數(shù)據(jù)模型,即json數(shù)據(jù)格式. 后端返回. 所以當一幅圖出來后,要對其上面有啥數(shù)據(jù),啥數(shù)據(jù)是后端返回的,要胸有成竹, 通過代碼+瀏覽器f12conson.log打印出來.

echarts官網(wǎng)上去看最簡單實例的教程,用flask展示出來

<!DOCTYPE html> <html> <head><meta charset="utf-8"><title>ECharts</title><!-- 引入 echarts.js --><script src="https://cdnjs.cloudflare.com/ajax/libs/echarts/4.0.2/echarts.min.js"></script> </head> <body> <!-- 為ECharts準備一個具備大小(寬高)的Dom --> <div id="main" style="width: 600px;height:400px;"></div> <script type="text/javascript">// 基于準備好的dom,初始化echarts實例var myChart = echarts.init(document.getElementById('main'));// 指定圖表的配置項和數(shù)據(jù)var option = {title: {text: 'ECharts 入門示例'},tooltip: {},legend: {data: ['銷量']},xAxis: {data: ["襯衫", "羊毛衫", "雪紡衫", "褲子", "高跟鞋", "襪子"]},yAxis: {},series: [{name: '銷量',type: 'bar',data: [5, 20, 36, 10, 10, 20]}]};// 使用剛指定的配置項和數(shù)據(jù)顯示圖表。myChart.setOption(option); </script> </body> </html>

echarts.min.js路徑替換下

flask啟動展示

from flask import Flask, render_templateapp = Flask(__name__)@app.route('/') def index():return render_template('demo.html')if __name__ == '__main__':app.run(debug=True)

先找一個合適的echarts圖,觀察它所需的接口數(shù)據(jù)格式,后設計接口

計劃使用echarts這個餅圖展示

它的源碼如下

option = {title : {text: '某站點用戶訪問來源',subtext: '純屬虛構',x:'center'},tooltip : {trigger: 'item',formatter: "{a} <br/>{b} : {c} (ozvdkddzhkzd%)"},legend: {orient: 'vertical',left: 'left',data: ['直接訪問','郵件營銷','聯(lián)盟廣告','視頻廣告','搜索引擎']},series : [{name: '訪問來源',type: 'pie',radius : '55%',center: ['50%', '60%'],data:[{value:335, name:'直接訪問'},{value:310, name:'郵件營銷'},{value:234, name:'聯(lián)盟廣告'},{value:135, name:'視頻廣告'},{value:1548, name:'搜索引擎'}],itemStyle: {emphasis: {shadowBlur: 10,shadowOffsetX: 0,shadowColor: 'rgba(0, 0, 0, 0.5)'}}}] };

下載后,修改echarts-pie.html源碼

<!DOCTYPE html> <html> <head><meta charset="utf-8"><title>ECharts</title><!-- 引入 echarts.js --><script src="/static/jquery.min.js"></script><script src="/static/echarts.min.js"></script> </head> <body><!-- 為ECharts準備一個具備大小(寬高)的Dom畫布 --> <div id="main" style="width: 600px;height:400px;"></div><script type="text/javascript">// 基于準備好的dom,初始化echarts實例var myChart = echarts.init(document.getElementById('main'));// 指定圖表的配置項和數(shù)據(jù)var option = {title: {text: '某站點用戶訪問來源',{# subtext: '純屬虛構',#}x: 'center'},tooltip: {trigger: 'item',formatter: "{a} <br/>{b} : {c} (ozvdkddzhkzd%)"},toolbox: {feature: {saveAsImage: {show: true}}},legend: {orient: 'vertical',left: 'left',{# data: ['直接訪問', '郵件營銷', '聯(lián)盟廣告', '視頻廣告', '搜索引擎']#}},series: [{name: '訪問來源',type: 'pie',radius: '55%',center: ['50%', '60%'],{# data: [#}{# {value: 335, name: '直接訪問'},#}{# {value: 310, name: '郵件營銷'},#}{# {value: 234, name: '聯(lián)盟廣告'},#}{# {value: 135, name: '視頻廣告'},#}{# {value: 1548, name: '搜索引擎'}#}{# ],#}itemStyle: {emphasis: {shadowBlur: 10,shadowOffsetX: 0,shadowColor: 'rgba(0, 0, 0, 0.5)'}}}]};//使用jq去訪問api獲取得到數(shù)據(jù).$.getJSON('/piedata', function (res) {option.legend.data = res.legendoption.series[0].data = res.data// 使用剛指定的配置項和數(shù)據(jù)顯示圖表-綁定數(shù)據(jù)myChart.setOption(option);}) </script> </body> </html>

我們知道了前端js需要的數(shù)據(jù)所需要的數(shù)據(jù)格式后,就從后端構造這樣的api,供前端調(diào)用

- api需返回數(shù)據(jù)的格式 {"data": [{"name": 200, "value": 49691}, {"name": 206, "value": 32}, {"name": 301, "value": 2}, {"name": 304, "value": 7584}, {"name": 403, "value": 1}, {"name": 404, "value": 3858}], "legend": [200, 206, 301, 304, 403, 404]}- js訪問接口方法 $.getJSON('/piedata', function (res) {option.legend.data = res.legendoption.series[0].data = res.datamyChart.setOption(option); //獲取后直接綁定 })

設計top10狀態(tài)碼的api

  • 目標是
即訪問 http://127.0.0.1:5000/piedata返回json數(shù)據(jù):{"data": [{"name": 200, "value": 49691}, {"name": 206, "value": 32}, {"name": 301, "value": 2}, {"name": 304, "value": 7584}, {"name": 403, "value": 1}, {"name": 404, "value": 3858}], "legend": [200, 206, 301, 304, 403, 404]}
  • 查庫后得到的結果
- 用sql語句做數(shù)據(jù)匯聚,查出status 和 對應的總數(shù), 按照狀態(tài)碼總數(shù)來排序 select status,sum(count) from log group by status;

查詢結果如下

  • flask寫api
- cur.fetchall返回的結果,需對其遍歷,重組一定格式的數(shù)據(jù) ((200, Decimal('49691')), (206, Decimal('32')), (301, Decimal('2')), (304, Decimal('7584')), (403, Decimal('1')), (404, Decimal('3858')))@app.route("/piedata") def piedata():sql = "select status,sum(count) from log group by status";cur = db.execute(sql)# 構造前端所需的數(shù)據(jù)結構res = {'legend': [],'data': []}for c in cur.fetchall():code = c[0]count = int(c[1])res['legend'].append(code)res['data'].append({'name': code,'value': count})print(res)return json.dumps(res)- 重組后數(shù)據(jù)格式如下 {'data': [{'name': 200, 'value': 49691}, {'name': 206, 'value': 32}, {'name': 301, 'value': 2}, {'name': 304, 'value': 7584}, {'name': 403, 'value': 1}, {'name': 404, 'value': 3858}], 'legend': [200, 206, 301, 304, 403, 404]}- 通過json模塊處理后返回給將這批數(shù)據(jù)返回給前端

最終訪問

實現(xiàn)前端html展示

@app.route("/") def index():return render_template("echarts-pie.html")

最終效果:

小結

轉(zhuǎn)載于:https://www.cnblogs.com/iiiiiher/p/8244145.html

總結

以上是生活随笔為你收集整理的[py]access日志入mysql-通过flask前端展示的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。