Python 3 解析 html

微微微笑發表於2017-11-20

資料:https://docs.python.org/3/library/html.parser.html

python 自帶了一個類,叫 HTMLParser。

我們用的時候需要自己定義一個類,繼承自 HTMLParser 。然後重寫一部分方法。

下面是我們常用的解析html的方法,可以看到在 HTMLParser 裡面,這些方法內容都是空的,也就是如果我們要用某個方法,我們得自己再我們的類裡面重寫這個方法。具體的每個方法的使用方式參見下文。

# Overridable -- finish processing of start+end tag: <tag.../>
    def handle_startendtag(self, tag, attrs):
        self.handle_starttag(tag, attrs)
        self.handle_endtag(tag)

    # Overridable -- handle start tag
    def handle_starttag(self, tag, attrs):
        pass

    # Overridable -- handle end tag
    def handle_endtag(self, tag):
        pass

    # Overridable -- handle character reference
    def handle_charref(self, name):
        pass

    # Overridable -- handle entity reference
    def handle_entityref(self, name):
        pass

    # Overridable -- handle data
    def handle_data(self, data):
        pass

    # Overridable -- handle comment
    def handle_comment(self, data):
        pass

    # Overridable -- handle declaration
    def handle_decl(self, decl):
        pass

    # Overridable -- handle processing instruction
    def handle_pi(self, data):
        pass

 

使用

1. 簡單解析

from html.parser import HTMLParser

class MyHTMLParser(HTMLParser):
    def handle_starttag(self, tag, attrs):
        print("Encountered a start tag:", tag)

    def handle_endtag(self, tag):
        print("Encountered an end tag :", tag)

    def handle_data(self, data):
        print("Encountered some data  :", data)

parser = MyHTMLParser()
parser.feed('<html><head><title>Test</title></head><body><h1>Parse me!</h1></body></html>')

這裡寫了一個類 MyHTMLParse ,繼承自 HTMLParser。然後重寫了 handle_xxx方法。

然後只要呼叫該類的 feed() 方法,將html格式的資料傳進去,遇到特定的資料,就會自動觸發相應的方法。比如遇到<html>就會觸發handle_starttag()方法進行處理。

執行結果如下:

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

2. 複雜解析

from html.parser import HTMLParser
from html.entities import name2codepoint

class MyHTMLParser(HTMLParser):
    def handle_starttag(self, tag, attrs):
        print("Start tag:", tag)
        for attr in attrs:
            print("     attr:", attr)

    def handle_endtag(self, tag):
        print("End tag  :", tag)

    def handle_data(self, data):
        print("Data     :", data)

    def handle_comment(self, data):
        print("Comment  :", data)

    def handle_entityref(self, name):
        c = chr(name2codepoint[name])
        print("Named ent:", c)

    def handle_charref(self, name):
        if name.startswith('x'):
            c = chr(int(name[1:], 16))
        else:
            c = chr(int(name))
        print("Num ent  :", c)

    def handle_decl(self, data):
        print("Decl     :", data)

parser = MyHTMLParser()

1)解析文件型別申明

傳入html資料如下:

parser.feed('<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">')

執行結果如下,可以看到會自動呼叫 handle_decl() 方法。

Decl     : DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"

2) 解析屬性

傳入html資料如下:

parser.feed('<img src="python-logo.png" alt="The Python logo">')

執行結果如下,可以看到會自動呼叫 handle_starttag()方法。

Start tag: img
     attr: ('src', 'python-logo.png')
     attr: ('alt', 'The Python logo')

3)解析資料以及結束標籤

傳入html資料如下:

parser.feed('<style type="text/css">#python { color: green }</style>')

執行結果如下,可以看到會自動呼叫 handle_data() 以及 handle_endtag()方法。

Start tag: style
     attr: ('type', 'text/css')
Data     : #python { color: green }
End tag  : style

4)解析備註

傳入html資料如下:

parser.feed('<!-- a comment --><!--[if IE 9]>IE-specific content<![endif]-->')

執行結果如下,可以看到會自動呼叫 handle_comment()方法。

Comment  :  a comment 
Comment  : [if IE 9]>IE-specific content<![endif]

5)解析實體字元

傳入html資料如下:

parser.feed('&gt;&#62;&#x3E;')

在html語言中 ‘>’這個符號,實體名稱為 &gt , 實體編號為 &#62。這裡 &#x3E表示16進位制數字,3E轉化過來和62 是一致的。

執行結果如下,可以看到會自動呼叫 handle_entityref() 來處理 &gt ,然後呼叫 handle_charref()來處理 &#62 以及 &#x3E。

Named ent: >
Num ent  : >
Num ent  : >

相關文章