Computer >> 컴퓨터 >  >> 프로그래밍 >> Python

Python으로 구조화된 문자열에서 필요한 데이터 추출하기: split()과 parse 모듈 활용법

소개

로그 파일이나 고정된 형식의 문자열에서 필요한 데이터를 추출해야 하는 경우가 자주 있습니다. 입력 형식이 미리 알려져 있다면 split() 메서드나 parse 모듈을 활용해 손쉽게 원하는 필드만 골라낼 수 있습니다. 이 글에서는 두 가지 방법을 예제와 함께 단계별로 살펴보겠습니다.

예제 데이터 준비하기

먼저 실습에 사용할 더미 로그 형식을 정의하겠습니다.

Report: <> - Time: <> - Player: <> - Titles: <> - Country: <>

실제 값이 채워진 로그는 다음과 같습니다.

report = 'Report: Daily_Report - Time: 2020-10-10T12:30:59.000000 - Player: Federer - Titles: 20 - Country: Switzerland'

방법 1: split() 메서드로 파싱하기

1단계: 구분자로 문자열 분리

로그를 관찰해 보면 각 필드가 하이픈(-)으로 구분되어 있습니다. 이 구분자를 기준으로 문자열을 나눠 보겠습니다.

fields = report.split(' - ')
name, time, player, titles, _ = fields

print(f"Output \n *** The report name {name} generated on {time} has {titles} titles for {player}.")

실행 결과

*** The report name Report: Daily_Report generated on Time: 2020-10-10T12:30:59.000000 has Titles: 20 titles for Player: Federer.

2단계: 불필요한 라벨 제거하기

결과를 보면 Report:, Time:, Player: 같은 라벨이 아직 남아 있습니다. 각 필드를 콜론(:) 기준으로 한 번 더 분리하면 순수한 값만 얻을 수 있습니다.

# 리포트 이름만 추출
formatted_name = name.split(':')[1]

# 선수 이름만 추출
formatted_player = player.split(':')[1]

# 타이틀 수만 추출 (정수형 변환)
formatted_titles = int(titles.split(':')[1])

# 시간 정보만 추출
new_time = time.split(': ')[1]

print(f"Output \n {formatted_name}, {new_time}, {formatted_player}, {formatted_titles}")

실행 결과

Daily_Report, 2020-10-10T12:30:59.000000, Federer, 20

3단계: ISO 형식의 타임스탬프 처리하기

추출한 시간 값은 ISO 8601 형식입니다. 그대로 사용해도 되지만, 필요하다면 datetime 객체로 변환할 수도 있습니다.

from datetime import datetime
formatted_date = datetime.fromisoformat(new_time)

print(f"Output \n{formatted_date}")

실행 결과

2020-10-10 12:30:59

4단계: 전체 과정을 하나의 함수로 통합하기

지금까지의 단계를 재사용 가능한 함수로 묶어 보겠습니다.

def parse_function(log):
    """
    Function : 주어진 형식의 로그를 파싱합니다.
    Report: <> - Time: <> - Player: <> - Titles: <> - Country: <>
    Args : log
    Return : 필요한 데이터
    """
    fields = log.split(' - ')
    name, time, player, titles, _ = fields

    # 리포트 이름만 추출
    formatted_name = name.split(':')[1]

    # 선수 이름만 추출
    formatted_player = player.split(':')[1]

    # 타이틀 수만 추출
    formatted_titles = int(titles.split(':')[1])

    # 시간 정보만 추출
    new_time = time.split(': ')[1]

    return f"{formatted_name}, {new_time}, {formatted_player}, {formatted_titles}"

if __name__ == '__main__':
    report = 'Report: Daily_Report - Time: 2020-10-10T12:30:59.000000 - Player: Federer - Titles: 20 - Country: Switzerland'
    data = parse_function(report)
    print(f"Output \n{data}")

실행 결과

Daily_Report, 2020-10-10T12:30:59.000000, Federer, 20

방법 2: parse 모듈로 더 간결하게 파싱하기

split() 방식은 여러 번 분리 작업을 거쳐야 해서 다소 번거롭습니다. parse 모듈을 사용하면 템플릿 하나만 정의하면 되기 때문에 훨씬 간단합니다.

먼저 모듈을 설치합니다.

pip install parse

로그 형식을 그대로 템플릿으로 만들고, 중괄호 안에 변수명을 지정합니다.

from parse import parse

report = 'Report: Daily_Report - Time: 2020-10-10T12:30:59.000000 - Player: Federer - Titles: 20 - Country: Switzerland'

# 로그 형식을 보고 템플릿 생성
template = 'Report: {name} - Time: {time} - Player: {player} - Titles: {titles} - Country: {country}'

# parse 실행 후 결과 확인
data = parse(template, report)
print(f"Output \n{data}")

실행 결과

<Result () {'name': 'Daily_Report', 'time': '2020-10-10T12:30:59.000000', 'player': 'Federer', 'titles': '20', 'country': 'Switzerland'}>

단 한 줄의 코드로 로그 전체가 딕셔너리 형태로 깔끔하게 추출되었습니다. 이제 개별 값에 접근해 보겠습니다.

print(f"Output \n {data['name']} - {data['time']} - {data['player']} - {data['titles']} - {data['country']}")

실행 결과

Daily_Report - 2020-10-10T12:30:59.000000 - Federer - 20 - Switzerland

마무리

지금까지 로그 파일에서 필요한 데이터를 파싱하는 두 가지 방법을 살펴보았습니다. split() 메서드는 외부 라이브러리 없이 바로 사용할 수 있다는 장점이 있지만, 필드마다 추가 분리 작업이 필요합니다. 반면 parse 모듈은 템플릿만 정의하면 한 번에 모든 값을 추출할 수 있어 코드가 간결하고 유지보수에도 유리합니다. 특별한 제약이 없다면 템플릿을 정의하고 parse 모듈을 사용하는 방식을 권장합니다.