BeautifulSoup는 HTML 및 XML 문서를 파싱하고 구조화된 데이터를 추출하기 위해 설계된 파이썬 라이브러리입니다. 특히 정적 웹 콘텐츠에서 태그, 속성, 텍스트 등을 효율적으로 탐색하고 조작하는 데 최적화되어 있습니다.
주요 특징
- DOM 유사 트리 구조 생성: 원본 마크업을 계층적 객체 트리로 변환하여 직관적인 탐색이 가능합니다.
- 자동 인코딩 감지 및 변환: 입력 문서의 인코딩을 자동으로 식별하고 유니코드로 정규화합니다.
설치 방법
pip install beautifulsoup4 lxml
lxml은 고성능 파서로, html.parser보다 약 3~5배 빠른 처리 속도를 제공합니다.
기본 사용법
다음 예제는 실제 웹 페이지 분석 시 자주 사용되는 패턴을 재구성한 것입니다:
from bs4 import BeautifulSoup
sample_markup = '''
<html lang="ko">
<head><meta charset="UTF-8"><title>테스트 페이지</title></head>
<body>
<article class="post" data-id="101">
<h2>첫 번째 글</h2>
<p>내용 요약 <a href="/article/101" rel="nofollow">자세히 보기</a></p>
</article>
<article class="post" data-id="102">
<h2>두 번째 글</h2>
<p>추가 설명 <a href="/article/102">읽기</a></p>
</article>
</body>
</html>
'''
parser = BeautifulSoup(sample_markup, 'lxml')
1. 태그 직접 접근
title_tag = parser.title # <title>테스트 페이지</title>
language = parser.html.get('lang') # 'ko'
2. 속성 안전 접근
first_link = parser.find('a')
url = first_link.get('href', '#') # 존재하지 않으면 기본값 반환
rel_attr = first_link.get('rel', []) # 리스트형 속성도 안전하게 처리
3. 조건 기반 탐색
# 단일 요소 찾기
main_article = parser.find('article', {'data-id': '101'})
# 여러 요소 수집 (CSS 클래스 필터링)
all_posts = parser.find_all('article', class_='post')
# 속성 값 정규식 매칭
external_links = parser.find_all('a', href=True, rel=re.compile(r'nofollow'))
4. 계층 관계 탐색
first_post = all_posts[0]
parent_section = first_post.parent.name # 'body'
next_post = first_post.find_next_sibling('article')
5. CSS 선택자 활용
# 복합 선택자
headers_in_articles = parser.select('article h2')
links_in_first_post = parser.select('article[data-id="101"] a')
nested_content = parser.select('body > article > p')
6. 텍스트 추출 전략
# 태그 내 순수 텍스트 (공백 정리 포함)
clean_text = parser.get_text(separator=' ', strip=True)
# 특정 태그의 텍스트만 추출
summary_para = parser.find('p')
plain_content = summary_para.get_text()
# 스타일/스크립트 내용은 string 속성으로 직접 접근
style_block = parser.find('style')
if style_block:
css_rules = style_block.string
실무 팁
- HTTP 응답에서
response.content를 사용해 바이너리 데이터를 직접 전달하면 인코딩 오류를 방지할 수 있습니다. - 대규모 파싱 작업에서는
lxml파서를 반드시 지정하고,html5lib는 DOM 호환성이 필요한 경우에만 사용하세요. - 존재 여부를 보장하지 않는 요소는
find()후is not None체크 또는select_one()과 함께or연산자를 활용해 안전하게 처리합니다.