지구정복

[Python] pandas 사용하기 (웹서버 로그 분석) 본문

데이터 엔지니어링 정복/Python

[Python] pandas 사용하기 (웹서버 로그 분석)

eeaarrtthh 2021. 9. 2. 11:41
728x90
반응형

출처: 빅데이터를 지탱하는 기술

 

책에 나와있는 코드가 실행이 안되서 제가 약간 수정을 했습니다~

 

 

 

 

책에 나온 예제 데이터는 더 이상 다운로드할 수 없길래 비슷한 웹서버 로그를 찾아서 진행했다.

아래에서 다운로드 받을 수 있다.

access.log
2.27MB

 

*운영환경

윈도우10

파이썬3.8.5

IDE: 이클립스pydev

 

1. 로그 데이터 파싱하기

해당 로그 데이터에서 필요한 부분만 정규표현식을 이용해서 추출하고 이를 pandas를 이용해서 데이터프레임 형식으로 만들어본다.

import re
import pandas as pd
import os.path

#로그 데이터를 확인하고 추출하고 싶은 데이터만 정규표현식을 이용해서 추출
#시간, 웹서버요청정보, 요청결과, 크기
pattern = re.compile( '^\S+ \S+ \S+ \[(.*)\] "(.*)" (\S+) (\S+) ".*"$')
    
def parse_access_log( path ):
    for line in open( path ):
        for m in pattern.finditer( line ):
            yield m.groups()

#데이터프레임 만들기
columns = [ 'time', 'request', 'status', 'bytes' ]
df = pd.DataFrame( parse_access_log( 'access.log' ), columns=columns )
#print( df )

#시간을 보기쉽게 형식 변경
df.time = pd.to_datetime( df.time, format='%d/%b/%Y:%X', exact=False )
print( df.head( 5 ) )

#데이터프레임을 csv파일로 저장
file = '.\\access_log.csv'
if os.path.isfile( file ):
    os.remove( file )
df.to_csv( 'access_log.csv', index=False )

위와 같이 파싱이 되었고 csv파일로 저장한다.

 

2. 시계열 데이터 집계하기

5월17일부터 5월 19일까지 하루마다 총 몇 개의 데이터가 있는 지를 집계해본다.

import pandas as pd

#파일 불러오기, 날짜를 datetime형식으로 가져온다.
df1 = pd.read_csv( 'access_log.csv', parse_dates=['time'] )

#시간을 인덱스로 지정한다.
df2 = df1.set_index( 'time' )

#인덱스에 의한 시간을 필터링한다. 2015.05.17 ~2015.05.19
df3 = df2.loc['2015-05-17':'2015-05-19']

#1일분의 액세스 수를 카운트한다.
print( df3.resample( '1d' ).size() )

혹시 numpy와 python버전이 맞지 않다는 에러가 뜨시는 분은 아래 글을 참고바랍니다.!

https://earthconquest.tistory.com/387

 

[python] 파이썬3.8.5에 numpy모듈 버전 맞지 않는다고 뜰 때

numpy 모듈 사용하려는데 아래와 같은 에러가 떴다.. * the python vhttps://numpy.org/devdocs/user/troubleshooting-importerror.htmlrsion is: python3.8 from "" * the numpy version is: "1.19.2" 대충 보니..

earthconquest.tistory.com

 

 

3. SQL을 이용해서 2와 똑같은 결과 출력하기

먼저 sql을 사용하다가 아래와 같은 에러가 뜰 수도 있다.

ImportError: DLL load failed: 지정된 모듈을 찾을 수 없습니다.

이는 인터프리터 라이브러리의 바이너리 파일들을 환경변수에 설정해주면 해결된다.

이는 다른 블로거님의 글을 참고하길 바란다. 자신의 아나콘다3 디렉터리 주소를 확인하고 환경변수로 설정하자.

나의 경우 c:/user/anaconda3/Library/bin에 있어서 이렇게 설정했다.

 

https://eboong.tistory.com/293

 

[Python] ImportError: DLL load failed: 지정된 모듈을 찾을 수 없습니다.

ImportError: DLL load failed: 지정된 모듈을 찾을 수 없습니다. > 터미널에서 python manage.py runserver를 치니까, 서버가 시작되지 않고, 저렇게 에러 메세지가 떠버렸다.. 윈도우키 + R 누르면 아래..

eboong.tistory.com

 

이제 sqlite3를 연결해서 db를 만들고 테이블을 만들고 데이터를 집어넣은 뒤 

pandas의 read_sql()를 이용해서 db의 쿼리결과를 데이터프레임형식으로 만들어보자.

import pandas as pd
import sqlite3

#sqlite3 DB만들기
conn = sqlite3.connect( 'WebLogSQL.db' )

#sqlite3에 연결해서 테이블 만들기
cursor = conn.cursor()
cursor = conn.execute('DROP TABLE IF EXISTS access_log;')
cursor = conn.execute('CREATE TABLE IF NOT EXISTS access_log (time test, request text, status text, bytes text);')

#변수를 이용한 insert 쿼리를 만든다. 
sql_insert = 'INSERT INTO access_log VALUES (?, ?, ?, ?);'

#csv파일을 불러와서 한 줄씩 쿼리를 실행해서 데이터를 insert한다.
f = open( './access_log.csv', 'r', encoding='utf-8' )
res = 0
for row in f.readlines():
    line = row.split(',')
    line = tuple( line )
    try:
        cursor.execute( sql_insert, line )
    except:
        continue
    res += 1
print( '쿼리 입력횟수: ', res )
conn.commit()

#해당 날짜의 데이터수 조회하기
sql_select = '''
SELECT substr( time, 1, 10 ) time, count(*) count
FROM access_log
WHERE time BETWEEN '2015-05-17' AND '2015-05-20'
GROUP BY 1
ORDER BY 1;
'''
df = pd.read_sql( sql_select, conn )
print( df )

#sqlite3연결 끊기
cursor.close()

위 코드를 실행하면 아래와 같은 결과가 나오고 이는 2에서의 결과와 같은 것을 알 수 있다.

 

 

728x90
반응형
Comments