오늘은 주어진 파일에서 문자열을 추출하고 다루는 일을 해볼 것입니다. 스텝별로 진행합니다.
시작!
1. 간단하게 샘플 텍스트가 저장된 test.txt 라는 파일을 읽는 작업입니다.
with open('test.txt') as f: fileContent = f.readlines() fileContent = [x.strip() for x in fileContent] print(fileContent)
실행결과
$ python readFile.py ['This is a test text1.', 'This is a test text2.']
2. 1과 동일하나 test.txt 라는 파일을 인자로 입력받는 기능을 갖습니다. (지난번 MD5 hash 구하기 편에서도 이러한 부분이 포함되어 있습니다)
import sys fileName = sys.argv[1] with open(fileName) as f: fileContent = f.readlines() fileContent = [x.strip() for x in fileContent] print(fileContent)
실행결과
$ python readFile.py test.txt ['This is a test text1.', 'This is a test text2.']
3. 1, 2는 결과가 쭉 나열되어 나옵니다. 이를 실제 test.txt 내 텍스트처럼 여러 줄로 보여주게 수정하겠습니다.
import sys fileName = sys.argv[1] with open(fileName) as f: fileContent = f.readlines() fileContent = [x.strip() for x in fileContent] for line in fileContent: print(line)
실행결과
$ python readFile.py test.txt This is a test text1. This is a test text2.
4. 이제 진짜 access.log 파일로 분석을 시작하려 합니다. 그리고 각 라인(결과)을 다시 blank를 기준으로 나눕니다.
import sys fileName = sys.argv[1] with open(fileName) as f: fileContent = f.readlines() fileContent = [x.strip() for x in fileContent] for line in fileContent: splitLine = line.split() print(splitLine)
실행결과
$ python readFile.py access.log ['192.168.176.17', '-', '-', '[21/May/2012:07:45:53', '+0900]', '"GET', '/images/sch_box_g04.gif', 'HTTP/1.1"', '304', '0'] ['192.168.176.17', '-', '-', '[21/May/2012:07:45:52', '+0900]', '"GET', '/images/sch_box_g07.gif', 'HTTP/1.1"', '304', '0'] ['192.168.176.17', '-', '-', '[21/May/2012:07:45:54', '+0900]', '"POST', '/meeting.deleteReservateDo.jsp', 'HTTP/1.1"', '200', '650944']
5. 실제 요청은 7번째 자리에 있네요. 인덱스로는 6이겠지요. (0부터 시작이니까) print(splitLine) 를 print(splitLine[6]) 로 바꾸고 다시 실행합니다.
실행결과
/left_menu.jsp /images/end_logo.gif /images/main_img.gif /images/quick.gif
6. 너무 속도가 안나서.. 빨리 빨리 넘어가겠습니다. 이제 확장자만 잘라서 리스트에 담고 출력하는 것까지 작업합니다.
import os import sys fileName = sys.argv[1] with open(fileName) as f: fileContent = f.readlines() extTable = {} fileContent = [x.strip() for x in fileContent] for line in fileContent: splitLine = line.split() ext = os.path.splitext(splitLine[6])[1] if ext.startswith('.'): ext = ext[1:] if len(ext) > 0: if ext in extTable: extTable[ext] += 1 else: extTable[ext] = 1 print(extTable)
실행결과
$ python readFile.py access.log {'css': 81, 'gif': 199, 'dev': 266, 'jpg': 3, 'js': 60, 'htc': 178, 'jsp': 70, 'ico': 4, 'ajax': 16, 'htm': 5, 'dev?query=4492&meetingday=20120529&popupDiv=Y': 1}
7. 어쩌고.dev?query= 와 같이 쿼리스트링이 달려있는 요청에 쿼리스트링이 다 딸려왔네요? 수정합니다.
import os import sys fileName = sys.argv[1] with open(fileName) as f: fileContent = f.readlines() extTable = {} fileContent = [x.strip() for x in fileContent] for line in fileContent: splitLine = line.split() ext = os.path.splitext(splitLine[6])[1] if ext.startswith('.'): ext = ext[1:] if '?' in ext: queryIndex = ext.find('?') ext = ext[:queryIndex] if len(ext) > 0: if ext in extTable: extTable[ext] += 1 else: extTable[ext] = 1 print(extTable)
실행결과
$ python readFile.py access.log {'css': 81, 'gif': 199, 'dev': 267, 'jpg': 3, 'js': 60, 'htc': 178, 'jsp': 70, 'ico': 4, 'ajax': 16, 'htm': 5}
8. 7번(혹은 6번)은 치명적인 단점이 있습니다. 뭘까요? 8번은 모두 생각하는 시간을 갖는 스텝입니다.
9. 7번(혹은 6번)은 확장자가 별도로 없는 요청, 예를 들어 / 같은 것은 카운트가 안됩니다. 패치합시다.
import os import sys fileName = sys.argv[1] with open(fileName) as f: fileContent = f.readlines() extTable = {} fileContent = [x.strip() for x in fileContent] for line in fileContent: splitLine = line.split() ext = os.path.splitext(splitLine[6])[1] if len(ext) > 0: if ext.startswith('.'): ext = ext[1:] if '?' in ext: queryIndex = ext.find('?') ext = ext[:queryIndex] if len(ext) > 0: if ext in extTable: extTable[ext] += 1 else: extTable[ext] = 1 else: if 'noExt' in extTable: extTable['noExt'] += 1 else: extTable['noExt'] = 1 print(extTable)
실행결과
$ python readFile.py access.log {'css': 81, 'gif': 199, 'dev': 267, 'jpg': 3, 'js': 60, 'noExt': 117, 'htc': 178, 'jsp': 70, 'ico': 4, 'ajax': 16, 'htm': 5}