반응형



파이썬의 HTMLParser 모듈을 이용하여 간단히 HTML 파싱하기


--------------------------------------------------

- 파이썬 공식 레퍼런스 사이트를 참고하였다.

(http://docs.python.org/2/library/htmlparser.html?highlight=html%20parsing)


- 파이썬 2.7 버젼에서 HTMLParser를 사용하였으나 파이썬 3에서 html.parser으로 변경되었다고 한다. (파이썬3 에서는 html.parser 모듈에서 HTMLParser클래스를 import 하면 2.7 버젼과 똑같이 사용할 수 있다. - from html.parser import HTMLParser)


- 레퍼런스 페이지에서 다양한 예제들을 확인할 수 있다.

--------------------------------------------------



Html 문서를 파싱하기 위해서는 HTMLParser 클래스를 상속하는 자식클래스를 작성하고 handler method들을 재정의 해야 한다.



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

#############
import HTMLParser
class MyHTMLParser(HTMLParser):
    def handler_starttag(self, tag,attrs):
        print "Encountered a start tag:", tag
    def handler_endtag(self, tag):
        print "Encountered an end tag:", tag
    def handler_data(self, data):
        print "Encountered some data :", data

parser = MyHTMLParser()
parser.feed('</span><title><span style="font-size: 12pt">Test</span></title>'
                 '<span style="font-size: 12pt;"></span>'
                 '<h1><span style="font-size: 12pt">Parser me!</span></h1>'
                 '<span style="font-size: 12pt">')

#############


위의 MyHTMLParser 클래스는

handler_starttag, handler_endtag, handler_data method를 재정의 하였으며 

이름에서 눈치 챘다 싶이 시작태그, 종료태그, "태그의 내용"을 만났을 때 각각 호출된다.

feed 메소드를 이용해 파싱하고자 하는 데이터를 str 형태로 전달한다.

아래는 실행했을 때 출력이다.


출력:

Encountered a start tag: html
Encountered a start tag: head
Encountered a start tag: title
Encountered some data  : Test
Encountered an end tag : title
Encountered an end tag : head
Encountered a start tag: body
Encountered a start tag: h1
Encountered some data  : Parse me!
Encountered an end tag : h1
Encountered an end tag : body
Encountered an end tag : html




feed(data)


HTMLParser 인스턴스의 feed(data) 메소드는 str 인자를 입력 받아 파싱한다.

불완전한 요소 데이터의 경우는 이후의 데이터가 추가되어 완전한 요소가 되거나 close()가 호출될 때까지 버퍼에 남아있는다.



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

#############
import HTMLParser
class MyHTMLParser(HTMLParser):
    def handler_starttag(self, tag,attrs):
        print "Encountered a start tag:", tag
    def handler_endtag(self, tag):
        print "Encountered an end tag:", tag
    def handler_data(self, data):
        print "Encountered some data :", data

parser = MyHTMLParser()
for chunk in ['&lt;sp''an&gt;buff''ered ''text&lt;/span&gt;']:
    parser.feed(chunk)

parser.close()
#############

 

출력




close()


버퍼에 남아있던 불완전한 tag 요소 데이터들을 강제로 파싱한다.

close() 메소드 호출 이후 추가적인 동작을 위해 

자식클래스에서 close() 메소드를 재정의 했더라도 

부모클래스의 close()를 잊지말고 호출하도록 하자.


1. 불완전한 tag 요소가 있는 경우.



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#############
import HTMLParser
class MyHTMLParser(HTMLParser):
    def handler_starttag(self, tag,attrs):
        print "Encountered a start tag:", tag
    def handler_endtag(self, tag):
        print "Encountered an end tag:", tag
    def handler_data(self, data):
        print "Encountered some data :", data
    def close(self):
        print "close!!!"
        HTMLParser.close(self)

parser = MyHTMLParser()
for chunk in ['<sp''an>buff''ered ''text</s']:
    parser.feed(chunk)

#############

출력

=> 'text' data까지 처리.




2. 불완전한 tag 요소가 남아있고 close()를 호출한 경우


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#############
import HTMLParser
class MyHTMLParser(HTMLParser):
    def handler_starttag(self, tag,attrs):
        print "Encountered a start tag:", tag
    def handler_endtag(self, tag):
        print "Encountered an end tag:", tag
    def handler_data(self, data):
        print "Encountered some data :", data
    def close(self):
        print "close!!!"
        HTMLParser.close(self)

parser = MyHTMLParser()
for chunk in ['<sp''an>buff''ered ''text</s']:
    parser.feed(chunk)

parser.close()
#############
출력

=> 버퍼에 남아있던 </s 까지 처리. 




reset()


instance를 reset 한다. 처리 되지 않은 데이터는 모두 잃어버린다.



getpos()


현재 라인 넘버와 offset을 return.



get_starttag_text()


제일 최근 확인한 start tag를 리턴한다. 





이밖에도


handler_startendtag(tag, attr) 

#XHTML-style의 tag를 만났을 때 (e.g. <img src =.../>) 호출된다.


handler_entityref(name) 

# 실제 참조를 만났을 때 호출된다.(e.g &lt, &gt, &quote 등)



handler_charref(name)  


# 문자 참조를 만났을 때 호출된다. 

# 문자 참조는 Unicode 번호로 참조한다. 10진수 및 16진수로 표현되며 다음과 같은 형태를 갖는다(&#NNN-10, &#xNNN-16)


handler_comment(data) 

# 코멘트(주석)를 만났을 때 호출된다. 
# (e.g. 를 만났을때 매개변수 data에는 'comment_hello'가 입력된 상태로 호출된다. 
# handler_comment( 'comment_hello' ) 이런 형태)


handler_decl(decl) 

# HTML doctype 선언을 만났을 때 호출된다 (e.g ) 
# 매개변수 decl 에는 <, !, > 를 제외된 상태로 전달된다. 
# (e.g : handler_decl( 'DOCTYPE html' ) 이런 형태라는 거지.)


handler_pi(data) 

# Processing Instruction 을 만났을 때 호출된다. 
# 이때 Processing InstructionSGML 문법에서 <?....> 혹은 <?....?> 으로 표현된 노드를 뜻한다. 


unknown_decl(data)

# 정의되지 않아 인식할 수 없는 선언을 만났을 때 호출 된다.
# <!...> 형태로 매개변수 data에는 ...가 입력된 상태로 호출된다.


--------------------------------------------------

- 파이썬 공식 레퍼런스 페이지를 참고하였다.

(http://docs.python.org/2/library/htmlparser.html?highlight=html%20parsing)


- 레퍼런스 페이지에서 다양한 예제들을 확인할 수 있다.

--------------------------------------------------



반응형