파이썬 표준 라이브러리의 html.parser 모듈에 정의된 HTMLParser 클래스는 HTML 및 XHTML 문서를 손쉽게 파싱할 수 있는 기능을 제공합니다. 이 클래스에는 태그, 데이터, 주석 등 다양한 HTML 요소를 식별할 수 있는 핸들러(handler) 메서드들이 포함되어 있습니다.
HTMLParser 기본 사용법
파서를 사용하려면 먼저 HTMLParser 클래스를 상속받는 새로운 클래스를 정의한 후, feed() 메서드에 파싱할 HTML 텍스트를 전달해야 합니다.
from html.parser import HTMLParser
class parser(HTMLParser):
pass
p = parser()
p.feed('<a href = "www.tutorialspoint.com"></a>')
오버라이딩해야 할 주요 메서드
HTMLParser를 실질적으로 활용하려면 아래의 메서드들을 상속받아 오버라이딩(재정의)해야 합니다.
handle_starttag(tag, attrs)
HTML 태그는 일반적으로 시작 태그와 종료 태그가 한 쌍을 이룹니다. 예를 들어 <head>와 </head>처럼요. handle_starttag() 메서드는 시작 태그를 처리하기 위해 호출됩니다.
태그 이름은 소문자로 변환되어 전달되며, attrs 인자는 태그의 <> 괄호 안에서 발견된 속성들을 담고 있습니다.
예를 들어, <a href = "www.tutorialspoint.com"></a> 태그를 파서 객체에 입력하는 경우를 살펴보겠습니다.
from html.parser import HTMLParser
class parser(HTMLParser):
def handle_starttag(self, tag, attrs):
print("Start tag:", tag)
for attr in attrs:
print(" attr:", attr)
p = parser()
p.feed('<a href = "www.tutorialspoint.com">')
실행 결과
Start tag: a
attr: ('href', 'www.tutorialspoint.com')
handle_endtag(tag)
이 메서드는 요소의 종료 태그를 처리하기 위해 호출됩니다.
def handle_endtag(self, tag):
print("end tag", tag)
handle_data(data)
이 메서드는 태그 사이에 존재하는 임의의 데이터(텍스트)를 처리하기 위해 호출됩니다. 다음 예제를 통해 세 가지 핸들러 메서드가 함께 동작하는 과정을 확인할 수 있습니다.
def handle_data(self, data):
print(data)
p = parser()
html = '''
<html>
<body>
<h1>Tutorialspoint</h1>
<b>Python standard library</b>
<p>HTML module</p>
</body>
</html>'''
p.feed(html)
실행 결과
Start tag: h1
Tutorialspoint
end tag h1
Start tag: b
Python standard library
end tag b
Start tag: p
HTML module
end tag p
HTMLParser의 기타 유용한 메서드
HTMLParser 클래스에는 위에서 소개한 메서드 외에도 다음과 같은 메서드들이 제공됩니다.
get_starttag_text()
가장 최근에 열린 시작 태그의 원본 텍스트를 그대로 반환합니다.
getpos()
현재 파서가 읽고 있는 문서 내 위치, 즉 줄 번호(line number)와 오프셋(offset)을 반환합니다.
handle_startendtag(tag, attrs)
handle_starttag()와 유사하지만, <img ... />와 같은 XHTML 스타일의 빈(empty) 태그를 만났을 때 호출됩니다.
handle_comment(data)
<!--comment-->와 같은 HTML 주석을 만났을 때 호출되며, 주석 내용이 data 인자로 전달됩니다.
이처럼 html.parser 모듈은 별도의 외부 라이브러리 설치 없이 순수 파이썬만으로 HTML 구조를 분석할 수 있게 해주는 가볍고 유용한 도구입니다.