일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | ||||
4 | 5 | 6 | 7 | 8 | 9 | 10 |
11 | 12 | 13 | 14 | 15 | 16 | 17 |
18 | 19 | 20 | 21 | 22 | 23 | 24 |
25 | 26 | 27 | 28 | 29 | 30 | 31 |
- androidstudio
- Flutter
- 아이피
- DART
- python
- Pillow
- H264
- DB호스팅
- 웹호스팅
- Firebase
- ffmpeg
- 다트
- 플러터
- 연준
- coding
- pandas
- 장고
- 이미지변환
- Django
- SNS 개발
- shortcut
- gifmp4변환
- accesslog
- O'NION
- 사이트 운영
- 안드로이드스튜디오
- nginx
- 비트코인
- 안드로이드코덱
- fed
- Today
- Total
누구나 할 수 있다.
파이썬 Pandas 라이브러리를 이용한 Access_log 분석 본문
오늘은 Pandas 라이브러리를 이용한 Nginx 웹서버 로그 분석을 해볼 예정입니다.
액세스 로그를 분석하여, 우리나라 IP가 서버에 얼마나 요청을 했는지에 대해 확인해 볼 예정입니다.
그래서 위의 목적을 달성하기 위해선, 아래의 준비물이 필요합니다.
- 우리나라의 IP 목록
- Nginx 서버의 Access log
- Pycharm 및 pandas 라이브러리
시작해보겠습니다.
분석 준비
일단 우리나라의 IP를 알아야 합니다.
lite.ip2location.com/korea-(republic-of)-ip-address-ranges
Korea (Republic of) IP Address Ranges
Complete list of IP address ranges in Korea (Republic of). The data source is IP2Location DB1 LITE database.
lite.ip2location.com
우리나라에 할당된 아이피 주소들이 나와있습니다.
모두 복사 한 후, 텍스트 파일로서 로컬에 저장해줍니다.
두번째로 access log 또한 준비해줍니다.
nginx 엔진의 log 파일은 따로 커스텀 설정을 해놓지 않았다면,
/var/log/nginx 폴더에 저장되어 있습니다.
Pycharm과 pandas를 설치했다면 준비는 끝났습니다.
분석 시작
일단 준비한 모든 데이터들을 읽어봅시다.
Pandas에서는 read_csv라는 아주 편리한 데이터 함수가 존재합니다.
제가 저장해놓은 데이터들의 확장자가 정확히 csv 인 것은 아니지만,
기본적으로 CSV 라는 것은 Comma Separated Values 의 약자로서, "콤마로 구분된 값"들이라 해석할 수 있습니다.
읽는 파일이 csv던, txt던 어떤 파일이든, 특정한 구분문자를 기준으로 데이터가 구분되어있다면 읽을 수 있습니다.
import pandas as pd
log = pd.read_csv('access_local.log', delimiter=' ')
ip = pd.read_csv('ip_range', delimiter='\t')
print(log)
print(ip)
테스트로 준비한 데이터들을 읽어줍니다.
유념해야할 것은, delimeter 라는 파라미터를 통해, 해당 파일 내의 구분문자가 무엇인지 알려주어야 한다는 점입니다.
정상적으로 데이터가 읽히는 것을 알 수 있습니다.
이제 본격적인 Pandas 기반 분석을 시작합니다.
이전에 간단한 Pandas 기본을 짚고 넘어가겠습니다.
Pandas에서 중요한 데이터 형태는 Dataframe, Series 두 가지입니다.
Dataframe은 기본적으로 표 전체를 의미하고,
Series는 표의 ‘열’에 해당하는 정보의 다발입니다.
Dataframe[‘test’]
명령어로 특정 열(series)을 잡아낼 수 있습니다.
dataframe[data[“Color”] == “Grey”]
로 특정 행(row)을 잡아낼 수 있습니다.
data_dict = {
“Fur Color”: [“Red”, “Blue”, “White”],
“Count”: [red_count, blue_count, white_count]
]
df = pandas.Dataframe(data_dict)
이런식으로 코드를 구성할 경우, 추출해 낸 데이터들을 기반으로 새로운 데이터프레임을 쉽게 만들 수도 있죠.
기본은 이렇습니다.
Pandas에서 제공하는 기능은 정말 많기 때문에 더 깊이 학습을 원하시는분은 직접 Documentation을 참고하시길 바랍니다.
여러가지 기능을 사용하긴 할텐데, 결국 조건문에 따라 특정 행들을 걸러내는 작업이 중요합니다.
import pandas as pd
log = pd.read_csv('access_local.log', delimiter=' ')
ip = pd.read_csv('ip_range', delimiter='\t')
start = ip.start.str.split('.')
end = ip.end.str.split('.')
먼저 대한민국 할당 IP 의 시작과 끝 범위를 따로 분리해냅니다.
...
splitted = log.ip.str.split('.')
ip_1 = splitted.str[0]
ip_2 = splitted.str[1]
ip_3 = splitted.str[2]
ip_4 = splitted.str[3]
filtered = pd.concat([ip_1, ip_2, ip_3, ip_4], axis=1)
filtered.columns = ['ip1', 'ip2', 'ip3', 'ip4']
filtered = filtered.astype("int64")
이후 access_log에 있는 "."으로 분리되는 접속 IP 4가지 숫자들을 분리하여 새로운 dataframe을 구축합니다.
뿐만 아니라, 기본적으로 csv 파일로부터 읽어온 데이터들은 str 형식의 데이터이기 때문에, integer 형태로 바꾸어 저장합니다.
count = 0
for x in range(len(start)):
temp = filtered[(filtered['ip1'] >= int(start[x][0])) & (filtered['ip1'] <= int(end[x][0]))]
if len(temp) == 0:
continue
temp = temp[(temp['ip2'] >= int(start[x][1])) & (temp['ip2'] <= int(end[x][1]))]
if len(temp) == 0:
continue
temp = temp[(temp['ip3'] >= int(start[x][2])) & (temp['ip3'] <= int(end[x][2]))]
if len(temp) == 0:
continue
temp = temp[(temp['ip4'] >= int(start[x][3])) & (temp['ip4'] <= int(end[x][3]))]
if len(temp) == 0:
continue
count += len(temp)
print(f"x: {x}, count: {count}")
print(count - len(log[log['ip'] == my_ip]))
할당되어있는 모든 IP 범위에 대해서 확인을 합니다.
중간중간 앞자리 IP 범위 내에 access log 의 IP 가 존재하지 않는다면, 다음 IP 범위로 건너뛰는 과정도 덧붙였습니다.
그래서 결과적으로,
약 2.5만개 가량의 접속로그를 분석한 결과, 국내 IP 주소에서 보낸 요청의 개수는
약 1.4만개인 것으로 확인할 수 있었습니다.
(본인 IP를 제외하면 약 3.5천개..ㅠ)
물론 이렇게 끝나긴 헀지만, 추가적으로 최적화를 할 수도 있습니다.
당장 생각나는건.. IP 주소들을 Sorting 하여, 순차적으로 확인해도 되는 IP 범위의 수를 줄여나가는 방법이 있지 않을까요?
긴글 읽어주셔서 감사합니다.
읽어주신 모두들 좋은 하루 보내시길 바랍니다.