Python 정규식 실무 완벽한 가이드: 데이터 추출부터 자동화까지

정규식 메타문자 이해하기

파이썬의 re 모듈을 활용한 패턴 매칭은 텍스트 처리의 핵심입니다. 일반적인 문자열 대입과는 달리 특수 문자를 사용하여 구조화된 정보를 찾아내야 합니다.

  • 일반 문자: 지정한 대로만 일치합니다.
  • \d: 숫자 0 에서 9 까지의 값을 매칭합니다.
  • .: 줄바꿈을 제외한 임의의 한 문자를 의미하며, 멀티라인 처리 시 re.S 옵션을 추가해야 합니다.
  • .+: 앞선 패턴을 최대로 반복하여 매칭하는 비최소 (greedy) 로직입니다.
  • []: 지정된 문자 집합 중 하나라도 일치하면 됩니다.
  • {n} / {n,m}: 앞선 규칙이 n 번 혹은 n 과 m 사이에 등장함을 요구합니다.
  • (): 캡처 그룹으로, 매칭된 특정 부분만 추출해낼 때 사용합니다.

스트링 내 JSON 데이터 파싱

와프터 데이터처럼 변수 형태로 묶인 문자열에서 JSON 데이터를 추출하여 CSV 파일로 변환하는 과정입니다. 문자열 이스케이프 (\) 가 필요할 때 raw string(r'') 사용을 권장합니다.

import re
import json
import pandas as pd

# 원본 데이터 문자열
raw_data = '''
var weather_data = [
    {"date": "20260201", "max_temp": "4", "min_temp": "-5"},
    {"date": "20260202", "max_temp": "3", "min_temp": "-7"}
]'''

# 대괄호 사이의 모든 내용을 찾습니다. .* 는 0 개 이상, ?는 최소 매칭을 의미하여 안정성을 높입니다.
pattern = r'\[\{.*?\}'
matches = re.findall(pattern, raw_data, flags=re.DOTALL)

# 첫 번째 결과물을 리스트 단위로 분리하고, JSON 문자열을 객체로 변환합니다
try:
    data_object = json.loads(matches[0])
    
    # Pandas DataFrame 생성 후 CSV 저장
    df = pd.DataFrame(data_object)
    df.to_csv('forecast.csv', index=False)
except IndexError:
    print("대괄호 내에 데이터를 찾을 수 없습니다.")

이 코드에서는 .+? 대신 .*? 를 사용하여 더 안전한 범위 설정을 적용했습니다. 또한 re.DOTALLre.S 와 동일하게 줄바꿈을 포함하여 매칭 가능하게 합니다.

고유 형식 데이터 검증

특정 양식의 정보가 올바른지 확인하거나 해당 구간만 분리해내는 연습입니다.

import re

# 작은 알파벳 연속 추출 테스트
test_text = 'Abc123defXyz'
lowercase_pattern = r'[a-z]+'
result_1 = re.findall(lowercase_pattern, test_text)
# 예상 결과: ['bc', 'def'] (대문자 제외)

# 중국 휴대폰 번호 검증 (11 자, 첫 자리 1, 두 자리 3~9)
phone_number = '13812345678'
# 1[3-9] 으로 시작하여 나머지 9 자리는 숫자
phone_pattern = r'^1[3-9]\d{9}$' 
is_valid = bool(re.match(phone_pattern, phone_number))
print(is_valid) # True

복잡한 텍스트에서의 정보 인출

여러 데이터가 섞여 있는 API 응답 형태에서 특정 키값을 찾아내는 방식입니다. 여기서는 비최소 매칭 (?*) 이 중요한 역할을 합니다.

api_response = '''
{
  "status": "ok",
  "items": [
    {"city": "서울", "temp": 20, "weather": "맑음"},
    {"city": "부산", "temp": 24, "weather": "구름"}
  ]
}
'''

# 단일 필드 추출 ("city": 뒤에 오는 값)
city_regex = r'"city": "(.+?)"'
cities = re.findall(city_regex, api_response)

# 복합 필드 동시 추출 (도시, 온도, 날씨)
full_info_regex = r'"city": "(.+?)".*"temp": (\d+).*"weather": "(.+?)"'
details = re.findall(full_info_regex, api_response)

print(f"추출된 도시: {cities}")
print(f"상세 정보: {details}")

HTML 태그 내 링크 추출

웹페이지 소스 코드에서 <a> 태그의 href 속성값을 모으는 작업입니다.

html_source = '''
<div class="nav">
  <a href="/page/1">다음</a>
  <a href="/page/2">목록</a>
  <span>공백 영역</span>
</div>
'''

# href= "..." 패턴을 찾아서 괄호 안 내용만 캡처
link_pattern = r'href=["\'](.+?)["\']'
urls = re.findall(link_pattern, html_source)

for url in urls:
    print(url)

실제 이미지 다운로드 스크립트 구현

요청 라이브러리인 requests 와 정규식을 결합하여 외부 서버의 이미지를 로컬에 저장하는 자동화 스크립트입니다.

import requests
import os
import time

# 대상 페이지 URL 정의
target_url = 'https://example-pic-site.com/gallery'
headers = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64)'
}

# 1. 페이지 소스 조회
res_page = requests.get(target_url, headers=headers)
html_content = res_page.text

# 2. 이미지 경로 추출
# img src 속성 값만을 정규식으로 추출
img_path_pattern = r']+src=["\']([^"\']+)["\']'
image_links = re.findall(img_path_pattern, html_content)

# 3. 저장 디렉토리 생성 및 파일 다운로드
save_dir = './downloads'
if not os.path.exists(save_dir):
    os.makedirs(save_dir)

for idx, link in enumerate(image_links):
    # 절대 경로 보정 (예시: 도메인 붙이기)
    full_img_url = link if link.startswith('http') else 'https://example-pic-site.com' + link
    
    try:
        img_res = requests.get(full_img_url, headers=headers)
        
        file_name = f'{save_dir}/image_{idx}.jpg'
        with open(file_name, 'wb') as f:
            f.write(img_res.content)
            
        print(f'다운로드 완료: {file_name}')
    except Exception as e:
        print(f'다운로드 실패: {e}')

    time.sleep(1) # 요청 간격 조절

위 과정은 먼저 메인 페이지의 HTML 을 받아 이미지 URL 목록을 얻고, 루프 안에서 각각의 이미지를 가져와 바이너리 데이터로 파일에 기록하는 전형적인 크롤링 구조입니다. 헤더 (User-Agent) 설정은 봇으로 인식되지 않도록 필수적입니다.

태그: python 정규식 requests 웹스크래핑 데이터처리

8월 14일 12:03에 게시됨