python分析nginx logログ
15500 ワード
1、背景紹介
本稿では、私のブログサイトのしばらくの間のアクセスログを例に分析します.使用する知識点基本データ型リスト、基本データ型辞書、 最終的に実現した機能解析によりログへのアクセス 2、考え方の進化
2.1、最初のステップでログを読み込む
上記のログ内容のフィールド情報は、訪問者ソース
そこで、まず1行分の内容を抽出し、その行の内容をグループ化して各フィールドの具体的な情報を記録し、その後、この行の分析手段を用いてログファイル全体を分析し、ログの各フィールドに一致するために
2.2、第二段階解析ログ
単行ログを正確に分析し、出力とフィルタをフォーマットする手段を追加します.
コードを実行し、印刷の結果を表示し、コンソール出力:
ログ・ファイルの合計行数、一致エラー(一致していない)の行数、一致する正しい行数を順に示します.
2.3、第三段階分析ログ
この時にインデックスがあることを発見しましたが、ヘッダーも右に移動しました.対応していません.ヘッダーを再設定する必要があります.
解析ログではアクセス数の上位を取得する必要がある場合が多いが,例えば上位
得られたデータの結果は
同様に、
2.4、第四段階生成レポート
このデータ型は、配列オブジェクト
2.5、ステップ5のログ収集
ログ分析が完了し、振り返って必要なのはログファイルを収集し、タイミング的に分析することである.
もちろん、サーバレベルのタイミングタスク機能タイミングの呼び出しスクリプト分析も可能です.
2.6、結果展示
前の進化過程に従って、最終的なコードは以下の通りです.
本稿では、私のブログサイトのしばらくの間のアクセスログを例に分析します.
re
モジュール正則マッチング、pandas
モジュールデータ処理、xlwt
モジュールexcel
書き込み等ip
のtop20
アクセスアドレスのtop20
アクセスクライアントua
のランキングが得られ、生成excel
レポート2.1、最初のステップでログを読み込む
nginx
ログ分析を行い、まず分析が必要なnginx
ログファイルを入手します.ログファイルの内容は固定的な定義方法があり、各行のログの中の特殊なフィールドは具体的な意味を表しています.例えば:95.143.192.110 - - [15/Dec/2019:10:22:00 +0800] "GET /post/pou-xi-he-jie-jue-python-zhong-wang-luo-nian-bao-de-zheng-que-zi-shi/ HTTP/1.1" 304 0 "https://www.ssgeek.com/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Safari/537.36"
上記のログ内容のフィールド情報は、訪問者ソース
ip
アクセス時間http
リクエスト方法・リクエストアドレスhttp
ステータスコード、今回のリクエストのバイトサイズrefer
メッセージ、クライアントua
識別子の順で表されるそこで、まず1行分の内容を抽出し、その行の内容をグループ化して各フィールドの具体的な情報を記録し、その後、この行の分析手段を用いてログファイル全体を分析し、ログの各フィールドに一致するために
re
ブロックを用いて正則的に一致させる必要がある.コードは以下の通りである.import re
obj = re.compile(r'(?P.*?)- - \[(?P
re
モジュール順パケットマッチング:ip
・time
・request
・status
bytes
・referer
・ua
・ip
・上記の内容で最終的に全ての訪問者ソースが印刷されたprint(result.groupdict())
さらに強化し、すべてのフィールドを出力し、直接印刷load_log()
すればよく、出力結果は次のように複数の辞書である.{'ip': '46.229.168.150 ', 'time': '24/Dec/2019:13:21:39 +0800', 'request': 'GET /post/zabbix-web-qie-huan-wei-nginx-ji-https HTTP/1.1', 'status': '301', 'bytes': '178', 'referer': '-', 'ua': 'Mozilla/5.0 (compatible; SemrushBot/6~bl; +http://www.semrush.com/bot.html)'}
2.2、第二段階解析ログ
単行ログを正確に分析し、出力とフィルタをフォーマットする手段を追加します.
load_log()
関数:lst
関数では、誤ったログ(「汚れたデータ」と同様)を避けるために、2つの空のリストが定義されているerror_lst
およびparse()
一致の結果を記録するために使用され、リストの各要素は一致する1行の日誌を表し、最後に合計行数が印刷され、一致する行数が印刷され、一致しない行数(エラー・ログの行数)parse()
関数:line
関数では、入力パラメータpandas
各行のパケットが一致する各フィールドを一度に処理し、処理が完了するとリスト要素に値を付与し、クライアントua識別子はいくつかの一般的なもののみをリストし、より正確に一致させるには、一般的なブラウザ(PC/モバイル)user-agent参照対照表を参照してください.マッチングルールをより正確に書けばいいimport re
import datetime
obj = re.compile(
r'(?P.*?)- - \[(?P
コードを実行し、印刷の結果を表示し、コンソール出力:
9692
542
9150
ログ・ファイルの合計行数、一致エラー(一致していない)の行数、一致する正しい行数を順に示します.
2.3、第三段階分析ログ
analyse()
モジュールによるログの解析lst
関数:解析フィルタリングした[{ip:xxx, api:xxx, status:xxxx, ua:xxx}]
リストをパラメータとして取り込み、リスト内のデータフォーマットはdf = pd.DataFrame(lst)
df
解析で得られたリストを類似表のタイプに変換し、コンソールの出力key
以下のように、処理後にデータごとにシーケンス番号が付けられ、1行目はヘッダに相当し、ヘッダは先に得られた辞書の中pd.value_counts(df['ip'])
ip status ... ua referer
0 95.143.192.110 200 ... mac -
1 95.143.192.110 304 ... mac -
2 95.143.192.110 304 ... mac -
3 95.143.192.110 304 ... mac https://www.ssgeek.com/
4 203.208.60.122 200 ... android -
... ... ... ... ... ...
9145 46.4.60.249 404 ... -
9146 46.4.60.249 404 ... -
9147 46.4.60.249 404 ... -
9148 46.4.60.249 404 ... -
9149 154.223.188.124 404 ... windows -
ip
取り出しip
集計数ip
の回数;結果1列目はpandas
2列目は回数reset_index()
デフォルトでは1列目を行インデックスとしていますので、データ全体を右に移動する必要がありますreset_index().rename(columns={"index": "ip", "ip": "count"})
インデックスを1つ再定義すれば、次のような効果が得られます. index ip
0 89.163.242.228 316
1 207.180.220.114 312
2 78.46.90.53 302
3 144.76.38.10 301
4 78.46.61.245 301
... ... ...
1080 203.208.60.85 1
1081 66.249.72.8 1
1082 141.8.132.13 1
1083 207.46.13.119 1
1084 203.208.60.7 1
この時にインデックスがあることを発見しましたが、ヘッダーも右に移動しました.対応していません.ヘッダーを再設定する必要があります.
ip count
0 89.163.242.228 316
1 207.180.220.114 312
2 78.46.90.53 302
3 78.46.61.245 301
4 144.76.38.10 301
... ... ...
1080 47.103.17.71 1
1081 42.156.254.92 1
1082 220.243.136.156 1
1083 180.163.220.61 1
1084 106.14.215.243 1
解析ログではアクセス数の上位を取得する必要がある場合が多いが,例えば上位
20
pandas
同様に便利であるiloc
スライスによってこのニーズを実現するiloc[:20, :]
:上位20
行を取り出し,すべての列を取り出し,最終的な処理コードは ip_count = pd.value_counts(df['ip']).reset_index().rename(columns={"index": "ip", "ip": "count"}).iloc[:20, :]
print(ip_count)
得られたデータの結果は
ip count
0 89.163.242.228 316
1 207.180.220.114 312
2 78.46.90.53 302
3 144.76.38.10 301
4 78.46.61.245 301
5 144.76.29.148 301
6 204.12.208.154 301
7 148.251.92.39 301
8 5.9.70.72 286
9 223.71.139.28 218
10 95.216.19.59 209
11 221.13.12.147 131
12 117.15.90.21 130
13 175.184.166.181 129
14 148.251.49.107 128
15 171.37.204.72 127
16 124.95.168.140 118
17 171.34.178.76 98
18 60.216.138.190 97
19 141.8.142.158 87
同様に、
request
・ua
等を同様に操作することができる2.4、第四段階生成レポート
xlwt
モジュールでpandas分析で得られたデータをexcel
表に書き込み、書き込む前にpandas処理後のデータを通常のデータに変換する必要がある ip_count_values = ip_count.values
request_count_values = request_count.values
ua_count_values = ua_count.values
このデータ型は、配列オブジェクト
numpy.ndarray
、例えば、[['89.163.242.228 ' 316]
['207.180.220.114 ' 312]
['78.46.90.53 ' 302]
['204.12.208.154 ' 301]
['144.76.29.148 ' 301]
['144.76.38.10 ' 301]
['78.46.61.245 ' 301]
['148.251.92.39 ' 301]
['5.9.70.72 ' 286]
['223.71.139.28 ' 218]
['95.216.19.59 ' 209]
['221.13.12.147 ' 131]
['117.15.90.21 ' 130]
['175.184.166.181 ' 129]
['148.251.49.107 ' 128]
['171.37.204.72 ' 127]
['124.95.168.140 ' 118]
['171.34.178.76 ' 98]
['60.216.138.190 ' 97]
['141.8.142.158 ' 87]]
xlwt
モジュール書き込みsheet
ページ毎sheet
ページ毎に対応する処理のデータを書き込む# excel
wb = xlwt.Workbook() # excel
sheet = wb.add_sheet("ip top20") # sheet
#
row = 0
sheet.write(row, 0, "ip") # , ,
sheet.write(row, 1, "count") # , ,
row += 1 #
for item in ip_count_values:
sheet.write(row, 0, item[0])
sheet.write(row, 1, item[1])
row += 1
2.5、ステップ5のログ収集
ログ分析が完了し、振り返って必要なのはログファイルを収集し、タイミング的に分析することである.
time
モジュールで時間を得て判断し、タイミングの分析を実現することができる.例えば、毎月3日の午前1時にログ分析を行うimport time
if __name__ == '__main__':
while 1:
stime = datetime.datetime.now().strftime("%d:%H:%M:%S")
if stime == "03:01:00:00":
lst, error_lst = load_log("nginx_access.log")
analyse(lst)
time.sleep(1)
もちろん、サーバレベルのタイミングタスク機能タイミングの呼び出しスクリプト分析も可能です.
2.6、結果展示
前の進化過程に従って、最終的なコードは以下の通りです.
import re
import datetime
import pandas as pd
import xlwt
obj = re.compile(
r'(?P.*?)- - \[(?P