python分析nginx logログ

15500 ワード

1、背景紹介
本稿では、私のブログサイトのしばらくの間のアクセスログを例に分析します.
  • 使用する知識点基本データ型リスト、基本データ型辞書、reモジュール正則マッチング、pandasモジュールデータ処理、xlwtモジュールexcel書き込み等
  • 最終的に実現した機能解析によりログへのアクセスiptop20アクセスアドレスのtop20アクセスクライアントuaのランキングが得られ、生成excelレポート
  • 2、考え方の進化
    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モジュール順パケットマッチング:iptimerequeststatusbytesrefereruaip・上記の内容で最終的に全ての訪問者ソースが印刷された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列目はpandas2列目は回数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
    

    解析ログではアクセス数の上位を取得する必要がある場合が多いが,例えば上位20pandas同様に便利である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
    

    同様に、requestua等を同様に操作することができる
    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