<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          Flask + echarts 輕松搞定 nginx 日志可視化

          共 6961字,需瀏覽 14分鐘

           ·

          2020-09-10 04:06

          文 |?太陽雪

          來源:Python 技術(shù)「ID: pythonall」

          最近,線上的業(yè)務(wù)系統(tǒng)不太穩(wěn)定,需要分析下訪問情況,能拿到的數(shù)據(jù)只有 nginx 服務(wù)器的訪問日志,不過難不倒我,用合適的工具,分分鐘做出圖形化展示,看看怎么做的吧

          思路

          nginx 訪問日志,記錄了每次客戶端請(qǐng)求,其中包括 ip、時(shí)間、使用的客戶端等信息

          通過解析每行數(shù)據(jù),提取這些信息,然后對(duì)信息進(jìn)行整理,并做一些必要的統(tǒng)計(jì)

          最后將統(tǒng)計(jì)數(shù)據(jù)展示出來,可以直觀地感知數(shù)據(jù)中蘊(yùn)含的問題

          基本思路就是這樣,不過知道和做到之間地距離還有很遠(yuǎn),為了達(dá)到目標(biāo),需要一些工具做支持

          由于數(shù)據(jù)是 nginx 訪問日志,所有不需要爬取,從服務(wù)器上下載就好

          整理處理過程,除了 python 本身一些功能外,還離不開 pandas 的支持

          最后數(shù)據(jù)展示部分,用的是 Flask + echarts,從頭寫,確實(shí)很有挑戰(zhàn),不過今天我們利用 TurboWay 同學(xué)的框架 bigdata_practice,就能輕松搞定

          閑話少敘,開始吧

          數(shù)據(jù)處理

          下載到 nginx 訪問日志,從 nginx 配置文件中可以查看日志存放地址,另外,本文源碼中有附帶示例日志文件,可下載使用

          日志文件為文本文件,每行記錄一條訪問情況,例如:

          124.64.19.27 - - [04/Sep/2020:03:21:12 +0800] "POST /api/hb.asp HTTP/1.1" 200 132 "http://erp.example.com/mainframe/main.html" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.117 Safari/537.36" "-"

          讀取文本文件的行,實(shí)現(xiàn)比較簡單,這里只對(duì)提取字段和通過 ip 確定省份做下說明

          提取

          提取字段的方法如下:

          import?re

          obj?=?re.compile(r'(?P.*?)-?-?\[(?P)

          result?=?obj.match(line)
          #?print(result.group("time"))
          #?ip處理
          ip?=?result.group("ip").split(",")[0].strip()?#?如果有兩個(gè)ip,取第一個(gè)ip

          #?狀態(tài)碼處理
          status?=?result.group("status")??#?狀態(tài)碼

          #?時(shí)間處理
          time?=?result.group("time").replace("?+0800",?"")?#?提取時(shí)間,并去掉時(shí)區(qū)信息
          t?=?datetime.datetime.strptime(time,?"%d/%b/%Y:%H:%M:%S")??#?格式化
          #?request處理
          request?=?result.group("request")
          a?=?request.split()[1].split("?")[0]??#?提取請(qǐng)求?url,去掉查詢參數(shù)

          #?user_agent處理
          ua?=?result.group("ua")
          if?"Windows?NT"?in?ua:
          ????u?=?"windows"
          elif?"iPad"?in?ua:
          ????u?=?"ipad"
          elif?"Android"?in?ua:
          ????u?=?"android"
          elif?"Macintosh"?in?ua:
          ????u?=?"mac"
          elif?"iPhone"?in?ua:
          ????u?=?"iphone"
          else:
          ????u?=?"其他設(shè)備"

          #?refer處理
          referer?=?result.group("referer")

          代碼看著長,其實(shí)邏輯很簡單,核心是提取信息的正則表達(dá)式,利用了命名分組的方式,匹配后,可以通過命名來提取數(shù)據(jù)

          對(duì)提取出的數(shù)據(jù),需要處理一下,比如請(qǐng)求時(shí)間,采用的是類似 UTC 時(shí)間格式,需要去掉時(shí)區(qū),并轉(zhuǎn)換為 datatime 類型

          另外就是的客戶端的處理,根據(jù)關(guān)鍵字,判斷客戶端類型

          將提取的信息,存入一個(gè) 詞典 對(duì)象中,即每行對(duì)于一個(gè) 詞典 對(duì)象,最后將一個(gè)個(gè)對(duì)象追加到一個(gè) 列表 對(duì)象中,帶進(jìn)一步處理

          獲取用戶省份

          為了后面對(duì)訪問者所在區(qū)域進(jìn)行分析,需要對(duì)一些字段做處理,例如將 ip 轉(zhuǎn)換為省份信息

          轉(zhuǎn)換主要利用的是百度的 ip 定位服務(wù)

          百度的 ip 定位服務(wù),通過認(rèn)證,可以獲得每日 3 萬次的免費(fèi)配額

          通過提供的 api 可以獲取 ip 地址所在的省名稱

          考慮到查詢效率和配額限制問題,最好對(duì) ip 定位的結(jié)果做個(gè)緩存:

          import?requests
          import?os

          ak?=?"444ddf895?...?a5ad334ee"?#?百度?ak?需申請(qǐng)

          #?ip?定位方法
          def?ip2province(ip):
          ????province?=?ipCache.get(ip,?None)
          ????if?province?is?None:
          ????????url?=?f"https://api.map.baidu.com/location/ip?ak={ak}&ip={ip}&coor=bd09ll"
          ????????try:
          ????????????province?=?json.loads(requests.get(url).text)['address'].split('|')[1]
          ????????????ipCache[ip]?=?province
          ????????????#?這里就需要寫入
          ????????????with?open("ip_cache.txt","a")?as?f:
          ????????????????f.write(ip?+?"\t"?+?province?+?"\n")
          ????????????return?province
          ????????except?Exception?as?e:
          ????????????return?"未知"
          ????else:
          ????????return?province

          #?初始化緩存
          ipCache?=?{}
          if?os.path.exists("ip_cache.txt"):
          ????with?open("ip_cache.txt",?"r")?as?f:
          ????????data?=?f.readline()
          ????????while?data:
          ????????????ip,?province?=?data.strip().split("\t")
          ????????????ipCache[ip]?=?province
          ????????????data?=?f.readline()
          • 首先需要申請(qǐng)一個(gè)百度 app key
          • 合成請(qǐng)求,通過 requests ?get,得到響應(yīng),從中提取到 ip 對(duì)應(yīng)的省份信息
          • 對(duì)應(yīng)地址緩存,將沒有緩存的結(jié)果存入 ipCache 詞典對(duì)象,并寫入 ip_cache.txt 文件,下次啟動(dòng)時(shí),用緩存文件中的內(nèi)容初始化 ipCache 詞典對(duì)象
          • 在每次需要獲取 ip 對(duì)應(yīng)地址時(shí),先檢查緩存,如果沒有才通過 api 獲取

          數(shù)據(jù)分析

          數(shù)據(jù)分析,就是對(duì)提取到的特征數(shù)據(jù)做統(tǒng)計(jì)加工,利用的是強(qiáng)大的 pandas

          通過數(shù)據(jù)處理過程,我們可以得到處理好的 列表 對(duì)象,列表對(duì)象很容易創(chuàng)建為 pandas 的 DataFrame

          接著,利用 pandas 的統(tǒng)計(jì)功能,將原始數(shù)據(jù)轉(zhuǎn)換為可以展示用的分析數(shù)據(jù)

          最后將數(shù)據(jù)存入 Excel 文件

          def?analyse(lst):
          ????df?=?pd.DataFrame(lst)??#?創(chuàng)建?DataFrame

          ????#?統(tǒng)計(jì)省份
          ????province_count_df?=?pd.value_counts(df['province']).reset_index().rename(columns={"index":?"province",?"province":?"count"})

          ????#?統(tǒng)計(jì)時(shí)段
          ????hour_count_df?=?pd.value_counts(df['hour']).reset_index().rename(columns={"index":?"hour",?"hour":?"count"}).sort_values(by='hour')

          ????#?統(tǒng)計(jì)客戶端
          ????ua_count_df?=?pd.value_counts(df['ua']).reset_index().rename(columns={"index":?"ua",?"ua":?"count"})

          ????#?數(shù)據(jù)存儲(chǔ)
          ????to_excel(province_count_df,?'data.xlsx',?sheet_name='省份')
          ????to_excel(hour_count_df,?'data.xlsx',?sheet_name='按時(shí)')
          ????to_excel(ua_count_df,?'data.xlsx',?sheet_name='客戶端')

          def?to_excel(dataframe,?filepath,?sheet_name):
          ????if?os.path.exists(filepath):j
          ????????excelWriter?=?pd.ExcelWriter(filepath,?engine='openpyxl')
          ????????book?=?load_workbook(excelWriter.path)
          ????????excelWriter.book?=?book
          ????????dataframe.to_excel(excel_writer=excelWriter,sheet_name=sheet_name,index=None,?header=None)
          ????????excelWriter.close()
          ????else:
          ????????dataframe.to_excel(filepath,?sheet_name=sheet_name,?index=None,?header=None)
          • analyse 方法,接受一個(gè) 列表 對(duì)象,即在數(shù)據(jù)整理部分得到的數(shù)據(jù)
          • 將數(shù)據(jù)創(chuàng)建為 DataFrame,利用 pandas 的 value_counts 方法對(duì)對(duì)應(yīng)字段數(shù)據(jù)進(jìn)行統(tǒng)計(jì),注意,value_counts 會(huì)做去重處理,從而統(tǒng)計(jì)出每個(gè)值出現(xiàn)的個(gè)數(shù)
          • 因?yàn)?value_counts 處理的結(jié)果,是一個(gè) Series 對(duì)象,索引為不重復(fù)的值,所以在用 reset_index 方法處理一下,將索引轉(zhuǎn)換為一個(gè)正常列,并對(duì)列名做了替換,以便后續(xù)處理更方便
          • 由于 value_counts 后的結(jié)果是按統(tǒng)計(jì)數(shù)量從多到少排列的,對(duì)應(yīng)按時(shí)間的統(tǒng)計(jì)有些奇怪,所以利用 sort_values 方法,按時(shí)間列做了重新排序
          • to_excel 方法是為了將數(shù)據(jù)導(dǎo)出為 excel,可以支持導(dǎo)入不同 sheet,以便做數(shù)據(jù)展示

          數(shù)據(jù)分析部分,可以從不同的角度對(duì)數(shù)據(jù)進(jìn)行統(tǒng)計(jì)分析,最終將需要展示的數(shù)據(jù)存入 Excel,當(dāng)然根據(jù)需要也可以存入其他數(shù)據(jù)庫

          數(shù)據(jù)展示

          從頭利用 Flask 和 echarts 做數(shù)據(jù)展示是可以的,不過需要處理更多的細(xì)節(jié)

          如果利用一些框架,快速做展示,然后再做局部的個(gè)性化調(diào)整

          這里用到的框架是 TurboWay 的 bigdata_practice,雖然功能比較單一,結(jié)構(gòu)不太靈活,不過用來搭建一個(gè)可用的數(shù)據(jù)展示系統(tǒng)還是沒問題的,重要的是可以通過源碼學(xué)習(xí)構(gòu)建思路的方法

          bigdata_practice git 地址為:https://github.com/TurboWay/bigdata_practice.git

          將其 clone 到本地

          git?clone?https://github.com/TurboWay/bigdata_practice.git

          然后按照依賴模塊,在 bigdata_practice 文件夾中,有個(gè) requirements.txt,里面列了項(xiàng)目所依賴的庫和組件

          關(guān)于如何構(gòu)建 requirements.txt 文件,可參考 《部署 Flask 應(yīng)用

          進(jìn)入 bigdata_practice 文件夾,用 pip 安裝依賴:

          pip?install?-r?requirements.txt

          注意:最好使用虛擬環(huán)境安裝,如何創(chuàng)建虛擬環(huán)境,可參考這篇文章

          安裝依賴之后,就可以啟動(dòng) Flask 服務(wù)了

          python?app.py

          ?*?Serving?Flask?app?"app"?(lazy?loading)
          ?*?Environment:?production
          ???WARNING:?This?is?a?development?server.?Do?not?use?it?in?a?production?deployment.
          ???Use?a?production?WSGI?server?instead.
          ?*?Debug?mode:?on
          ?*?Restarting?with?stat
          ?*?Debugger?is?active!
          ?*?Debugger?PIN:?137-055-644
          ?*?Running?on?http://127.0.0.1:5000/?(Press?CTRL+C?to?quit)

          如果一切正常,可以訪問 localhost:5000,查看數(shù)據(jù)展示效果

          這里對(duì)項(xiàng)目中的需要定制的部分做下說明

          在 ironman 目錄下,app.py 為 Flask 服務(wù)主代碼,其中定義了系統(tǒng)的訪問路徑,比如首頁、線圖、餅圖等,這里可以根據(jù)自己的需求添加或刪改

          每個(gè)訪問路徑對(duì)應(yīng)一個(gè)頁面模板,模板文件存放在,templates 文件夾下,如果需要調(diào)整菜單,需要對(duì)每個(gè)模板頁面中的菜單部分進(jìn)行修改,以調(diào)整菜單項(xiàng)目以及被激活的菜單

          data.py 定義了展示數(shù)據(jù)的讀取接口,相當(dāng)于一個(gè)數(shù)據(jù)層,依賴于 nginx_log_data.py,將數(shù)據(jù)設(shè)置為,方便展示的結(jié)構(gòu),如果需要展示更多的圖形,需要根據(jù)展示效果,修改或添加新的數(shù)據(jù)接口

          nginx_log_data.py 從 Excel 文件中讀取需要展示的數(shù)據(jù),Excel 中的數(shù)據(jù),就是 數(shù)據(jù)分析 部分得到的結(jié)果,這里利用 pandas 讀取 Excel 的功能,如果需要展示更多的分析數(shù)據(jù),可以在這里添加數(shù)據(jù)讀取結(jié)果,另外通過調(diào)整 data.py 以及相應(yīng)的頁面模板文件,將數(shù)據(jù)得以展示

          這里,我們就 24小時(shí)訪問趨勢(shì)、客戶端占比以及用戶分布做了展示,效果如下:

          24小時(shí)訪問趨勢(shì)

          客戶端占比

          用戶分布

          實(shí)踐

          下載源碼后,先安裝項(xiàng)目依賴

          pip?install?-r?requirements.txt

          示例用的 nginx 訪問日志,在 nginx_access.zip 壓縮包里,先解壓到當(dāng)前目錄

          然后申請(qǐng)百度API,獲取到 ak,修改到 analyse\baidu_api.py 的 13 行

          將命令行切換到代碼目錄下,否則可能出現(xiàn)文件找不到的錯(cuò)誤

          執(zhí)行數(shù)據(jù)分析腳本:

          python?.\analyse\main.py

          最后啟動(dòng) Flask 服務(wù):

          python?.\ironman\app.py

          總結(jié)

          今天利用 pandas、Flask、echarts 對(duì) nginx 服務(wù)器的訪問日志做了簡單分析和展示,完成任務(wù)的同時(shí),學(xué)習(xí)和實(shí)踐了如何通過一些簡單的工具和方法構(gòu)造一個(gè)數(shù)據(jù)展示平臺(tái)的過程

          文章主要說明了構(gòu)建思路和需要注意的部分,具體細(xì)節(jié),請(qǐng)下載示例代碼,運(yùn)行,同時(shí)歡迎交流探討

          參考

          • https://www.cnblogs.com/ssgeek/p/12119657.html
          • https://blog.csdn.net/whaoxysh/article/details/22295317
          • http://lbsyun.baidu.com/index.php?title=webapi/ip-api
          • http://lbsyun.baidu.com/apiconsole/key
          • https://blog.csdn.net/unsterbliche/article/details/80578606
          • https://github.com/TurboWay/bigdata_practice

          PS公號(hào)內(nèi)回復(fù)「Python」即可進(jìn)入Python 新手學(xué)習(xí)交流群,一起 100 天計(jì)劃!


          老規(guī)矩,兄弟們還記得么,右下角的 “在看” 點(diǎn)一下如果感覺文章內(nèi)容不錯(cuò)的話,記得分享朋友圈讓更多的人知道!

          代碼獲取方式

          識(shí)別文末二維碼,回復(fù):200909

          瀏覽 59
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  黄色一级在线观看 | 成人黄色大片在线观看 | 中国三级片91 | 老骚逼视频| 亚洲乱码中文字幕 |