[Python] HTTP web server log dataframe으로 불러오기 (with pandas)

2022. 2. 13. 00:43·Programming/Python
반응형

이번에 프로젝트를 진행하면서 웹 로그 서버의  raw level을 직접 보고 전처리할 기회를 접하게 되었다. 어쨌든 웹로그를 데이터프레임화 시켜서 분포를 보고 데이터 탐색을 진행해야하기 때문에 공통된 룰로 전처리를 하고 데이터프레임화를 시켜야 해서 검색하다보니 아래와 같은 링크를 발견했고, 이에 대해 번역을 해서 기록해두려고 한다. 

 

https://mmas.github.io/read-apache-access-log-pandas

 

Read Apache HTTP server access log with Pandas

In this post we'll see how to read our Apache HTTP server access log into a Pandas dataframe. First of all, we should take a look to the logging do...

mmas.github.io


1. Web log 살펴보기

우선 로깅 문서를 살펴보고 그 형식에 대해 알아보도록 하자. 일반적으로 다음과 같은 로그 형식을 사용하게 된다. (나도 회사에서 아래와 같은 형식의 로그를 사용했다)

%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-agent}i\"

 

  • %h : client의 IP주소(원격 호스트)
  • %l : RFC 1413 identity
  • %u : HTTP 인증에 의해 결정되는 사용자 ID(보통 - - 일 경우가 많음)
  • %t : [일/월/년:시:분:초 영역]형식의 시간
  • \"%r%\" : 요청 문자열 "method resource protocol" (일반적으로 우리가 접속했을 때의 url이다)
  • %>s : status code (에러및 정상 코드)
  • %0 : 요청 사이즈
  • \"%{Referer}i\" : referrer HTTP url
  • \"%{User-Agent}i\" : User Agent HTTP request

예시를 들면, 아래와 같은게 하나의 요청이 들어올 때 쌓이는 로그라고 볼 수 있다.(아래의 예시는 댓글에서 참고해서 가져왔다)

103.15.66.130 - - [03/Aug/2018:10:50:47 +0000] "GET /v1/?act=encrypt&customerid=881329143866&customeremail=priyank@gowebbaby.com&customername=priyank%20gandhe&cdata=&domain=aaatheme4.myshopify.com HTTP/1.1" 200 212 "https://aaatheme4.myshopify..." "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.75 Safari/537.36"

2. Pandas Package로 불러오기

이러한 정의로 판다스에서 문자열을 seperate할 때 고려해야한다. 

pandas는 따옴표 붙은 문자를 건너띄기 위해서 그 따옴표 사이의 구분기호 문자를 분리하지는 않지만 그 이상에서는 제대로 작동을 하지 않는다. 그래서 열을 구분하기 위해서는 보다 복잡한 정규식이 필요하다. 우리는 9개의 필드를 얻기 위해 각 줄을 구분하는 정규식을 정읳야 한다. 

그것은 큰따옴표 또는 대괄호와 일치해야 한다. 그럼 아래와 같은 구분자로 분리해야 한다. 

\s                           # space로 분리
(?=(?:[^"]*"[^"]*")*[^"]*$)  # 큰 따옴표로 둘러쌓여있지 않는
(?![^\[]*\])                 # 대괄호 안에 둘러쌓여있지 않는

시간, reauest url, referer url, user agent들이 큰따옴표나 대괄호 안에 둘러쌓여있기 때문에 우리는 그 대괄호나 쌍따옴표를 제거할 함수가 필요하다. 그리고 시간은 datetime 으로 타입을 바꿔주어야 한다. 

from datetime import datetime
import pytz

def parse_str(x):
    """
    Returns the string delimited by two characters.

    Example:
        `>>> parse_str('[my string]')`
        `'my string'`
    """
    return x[1:-1]

def parse_datetime(x):
    '''
    Parses datetime with timezone formatted as:
        `[day/month/year:hour:minute:second zone]`

    Example:
        `>>> parse_datetime('13/Nov/2015:11:45:42 +0000')`
        `datetime.datetime(2015, 11, 3, 11, 45, 4, tzinfo=<UTC>)`

    Due to problems parsing the timezone (`%z`) with `datetime.strptime`, the
    timezone will be obtained using the `pytz` library.
    '''
    dt = datetime.strptime(x[1:-7], '%d/%b/%Y:%H:%M:%S')
    dt_tz = int(x[-6:-3])*60+int(x[-3:-1])
    return dt.replace(tzinfo=pytz.FixedOffset(dt_tz))

그리고 우리는 pandas를 이용해서  log 파일을 불러올 수 있다. 우리는 2번째와 3번째 컬럼은 가져오지 않을거다.

import re
import pandas as pd

data = pd.read_csv(
    'data/access.log',
    sep=r'\s(?=(?:[^"]*"[^"]*")*[^"]*$)(?![^\[]*\])',
    engine='python',
    na_values='-',
    header=None,
    usecols=[0, 3, 4, 5, 6, 7, 8],
    names=['ip', 'time', 'request', 'status', 'size', 'referer', 'user_agent'],
    converters={'time': parse_datetime,
                'request': parse_str,
                'status': int,
                'size': int,
                'referer': parse_str,
                'user_agent': parse_str})

그럼 아래와 같이 데이터가 분리되어 dataframe 형식으로 저장된다.

출처 :&nbsp;https://mmas.github.io/read-apache-access-log-pandas

 

여기서 request 문을 좀 더 분리해서 url만 따로 뽑아내고 싶다면, 아래와 같은 문장을 사용하면 된다.

request = data.pop('request').str.split()
data['resource'] = request.str[1]

 

이 아래의 문장들은 다른 데이터에 특수화된 코드 들이어서 생략하도록 한다. 

추가적으로 에러로그 또한 같이 로깅하면서 에러가 발생할 떄가 있는데 이 경우는 아래와 같이 코드를 붙여 데이터를 좀 수정한 다음 다시 불러오면 된다.(에러문 사이에 큰따옴표로 이루어진 문장들이 있을 경우 발생한다)

with open('data/access.log') as infile:
    with open('data/access.log', 'w') as outfile:
        for line in infile:
            outfile.write(line.replace('\\"', ''))
pd.read_csv( 'data/access.log', ...)

 

 

개인적으로 위 깃헙글이 웹로그를 분석할 때 도움이 많이 되어 다른 이들에게도 도움이 되길 바라며.. 이글을 마친다.

반응형

'Programming > Python' 카테고리의 다른 글

[Python] inspect 모듈의 getsource() 함수  (0) 2022.06.12
[Python/Oracle] cx_Oracle timeout 설정하기  (0) 2022.04.10
[Python] 주피터 노트북 테마 변경하기  (3) 2021.05.17
[Python]Pytorch - RuntimeError:Error(s) in loading state_dict ... : Missing key(s) in state_dict: ... Unexpected key(s) in state_dict:... GPU 병렬 사용 문제  (0) 2021.04.30
[Python] Data Frame apply 함수 병렬처리 하는 방법  (0) 2021.04.15
'Programming/Python' 카테고리의 다른 글
  • [Python] inspect 모듈의 getsource() 함수
  • [Python/Oracle] cx_Oracle timeout 설정하기
  • [Python] 주피터 노트북 테마 변경하기
  • [Python]Pytorch - RuntimeError:Error(s) in loading state_dict ... : Missing key(s) in state_dict: ... Unexpected key(s) in state_dict:... GPU 병렬 사용 문제
자동화먹
자동화먹
많은 사람들에게 도움이 되는 생산적인 기록하기
    반응형
  • 자동화먹
    자동화먹의 생산적인 기록
    자동화먹
  • 전체
    오늘
    어제
    • 분류 전체보기 (144)
      • 생산성 & 자동화 툴 (30)
        • Notion (24)
        • Obsidian (0)
        • Make.com (1)
        • tips (5)
      • Programming (37)
        • Python (18)
        • Oracle (6)
        • Git (13)
      • AI Study (65)
        • DL_Basic (14)
        • ML_Basic (14)
        • NLP (21)
        • Marketing&Recommend (4)
        • chatGPT (0)
        • etc (12)
      • 주인장의 생각서랍 (10)
        • 생각정리 (4)
        • 독서기록 (6)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    노션
    ML
    Github
    dl
    notion
    git commit
    seq2seq
    노션첫걸음
    파이토치로 시작하는 딥러닝 기초
    Python
    cnn
    빅데이터
    딥러닝
    자연어처리
    빅데이터분석
    Jupyter notebook
    pytorch
    gcp
    Google Cloud Platform
    파이토치
    머신러닝
    Transformer
    GPT
    데이터베이스
    LSTM
    git
    기초
    nlp
    데이터분석
    python기초
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.3
자동화먹
[Python] HTTP web server log dataframe으로 불러오기 (with pandas)
상단으로

티스토리툴바