html.parser --- 簡(jiǎn)單的 HTML 和 XHTML 解析器?

源代碼: Lib/html/parser.py


這個(gè)模塊定義了一個(gè) HTMLParser 類(lèi),為 HTML(超文本標記語(yǔ)言)和 XHTML 文本文件解析提供基礎。

class html.parser.HTMLParser(*, convert_charrefs=True)?

創(chuàng )建一個(gè)能解析無(wú)效標記的解析器實(shí)例。

如果 convert_charrefsTrue (默認值),則所有字符引用( script/style 元素中的除外)都會(huì )自動(dòng)轉換為相應的 Unicode 字符。

一個(gè) HTMLParser 類(lèi)的實(shí)例用來(lái)接受 HTML 數據,并在標記開(kāi)始、標記結束、文本、注釋和其他元素標記出現的時(shí)候調用對應的方法。要實(shí)現具體的行為,請使用 HTMLParser 的子類(lèi)并重載其方法。

這個(gè)解析器不檢查結束標記是否與開(kāi)始標記匹配,也不會(huì )因外層元素完畢而隱式關(guān)閉了的元素引發(fā)結束標記處理。

在 3.4 版更改: convert_charrefs 關(guān)鍵字參數被添加。

在 3.5 版更改: convert_charrefs 參數的默認值現在為 True。

HTML 解析器的示例程序?

下面是簡(jiǎn)單的 HTML 解析器的一個(gè)基本示例,使用 HTMLParser 類(lèi),當遇到開(kāi)始標記、結束標記以及數據的時(shí)候將內容打印出來(lái)。

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>')

輸出是:

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

HTMLParser 方法?

HTMLParser 實(shí)例有下列方法:

HTMLParser.feed(data)?

填充一些文本到解析器中。如果包含完整的元素,則被處理;如果數據不完整,將被緩沖直到更多的數據被填充,或者 close() 被調用。data 必須為 str 類(lèi)型。

HTMLParser.close()?

如同后面跟著(zhù)一個(gè)文件結束標記一樣,強制處理所有緩沖數據。這個(gè)方法能被派生類(lèi)重新定義,用于在輸入的末尾定義附加處理,但是重定義的版本應當始終調用基類(lèi) HTMLParserclose() 方法。

HTMLParser.reset()?

重置實(shí)例。丟失所有未處理的數據。在實(shí)例化階段被隱式調用。

HTMLParser.getpos()?

返回當前行號和偏移值。

HTMLParser.get_starttag_text()?

返回最近打開(kāi)的開(kāi)始標記中的文本。 結構化處理時(shí)通常應該不需要這個(gè),但在處理“已部署”的 HTML 或是在以最小改變來(lái)重新生成輸入時(shí)可能會(huì )有用處(例如可以保留屬性間的空格等)。

下列方法將在遇到數據或者標記元素的時(shí)候被調用。他們需要在子類(lèi)中重載?;?lèi)的實(shí)現中沒(méi)有任何實(shí)際操作(除了 handle_startendtag() ):

HTMLParser.handle_starttag(tag, attrs)?

This method is called to handle the start tag of an element (e.g. <div id="main">).

tag 參數是小寫(xiě)的標記名。attrs 參數是一個(gè) (name, value) 形式的列表,包含了所有在標記的 <> 括號中找到的屬性。name 轉換為小寫(xiě),value 的引號被去除,字符和實(shí)體引用都會(huì )被替換。

實(shí)例中,對于標簽 <A >,這個(gè)方法將以下列形式被調用 handle_starttag('a', [('href', 'https://www.cwi.nl/')]) 。

html.entities 中的所有實(shí)體引用,會(huì )被替換為屬性值。

HTMLParser.handle_endtag(tag)?

此方法被用來(lái)處理元素的結束標記(例如: </div> )。

tag 參數是小寫(xiě)的標簽名。

HTMLParser.handle_startendtag(tag, attrs)?

類(lèi)似于 handle_starttag(), 只是在解析器遇到 XHTML 樣式的空標記時(shí)被調用( <img ... />)。這個(gè)方法能被需要這種特殊詞法信息的子類(lèi)重載;默認實(shí)現僅簡(jiǎn)單調用 handle_starttag()handle_endtag() 。

HTMLParser.handle_data(data)?

這個(gè)方法被用來(lái)處理任意數據(例如:文本節點(diǎn)和 <script>...</script> 以及 <style>...</style> 中的內容)。

HTMLParser.handle_entityref(name)?

這個(gè)方法被用于處理 &name; 形式的命名字符引用(例如 &gt;),其中 name 是通用的實(shí)體引用(例如: 'gt')。如果 convert_charrefsTrue,該方法永遠不會(huì )被調用。

HTMLParser.handle_charref(name)?

這個(gè)方法被用來(lái)處理 &#NNN;&#xNNN; 形式的十進(jìn)制和十六進(jìn)制字符引用。例如,&gt; 等效的十進(jìn)制形式為 &#62; ,而十六進(jìn)制形式為 &#x3E; ;在這種情況下,方法將收到 '62''x3E' 。如果 convert_charrefsTrue ,則該方法永遠不會(huì )被調用。

HTMLParser.handle_comment(data)?

這個(gè)方法在遇到注釋的時(shí)候被調用(例如: <!--comment--> )。

例如, <!-- comment --> 這個(gè)注釋會(huì )用 ' comment ' 作為參數調用此方法。

Internet Explorer 條件注釋?zhuān)╟ondcoms)的內容也被發(fā)送到這個(gè)方法,因此,對于 <!--[if IE 9]>IE9-specific content<![endif]--> ,這個(gè)方法將接收到 '[if IE 9]>IE9-specific content<![endif]' 。

HTMLParser.handle_decl(decl)?

這個(gè)方法用來(lái)處理 HTML doctype 申明(例如 <!DOCTYPE html> )。

decl 形參為 <!...> 標記中的所有內容(例如: 'DOCTYPE html' )。

HTMLParser.handle_pi(data)?

此方法在遇到處理指令的時(shí)候被調用。data 形參將包含整個(gè)處理指令。例如,對于處理指令 <?proc color='red'> ,這個(gè)方法將以 handle_pi("proc color='red'") 形式被調用。它旨在被派生類(lèi)重載;基類(lèi)實(shí)現中無(wú)任何實(shí)際操作。

備注

HTMLParser 類(lèi)使用 SGML 語(yǔ)法規則處理指令。使用 '?' 結尾的 XHTML 處理指令將導致 '?' 包含在 data 中。

HTMLParser.unknown_decl(data)?

當解析器讀到無(wú)法識別的聲明時(shí),此方法被調用。

data 形參為 <![...]> 標記中的所有內容。某些時(shí)候對派生類(lèi)的重載很有用?;?lèi)實(shí)現中無(wú)任何實(shí)際操作。

例子?

下面的類(lèi)實(shí)現了一個(gè)解析器,用于更多示例的演示:

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()

解析一個(gè)文檔類(lèi)型聲明:

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

解析一個(gè)具有一些屬性和標題的元素:

>>>
>>> parser.feed('<img src="python-logo.png" alt="The Python logo">')
Start tag: img
     attr: ('src', 'python-logo.png')
     attr: ('alt', 'The Python logo')
>>>
>>> parser.feed('<h1>Python</h1>')
Start tag: h1
Data     : Python
End tag  : h1

scriptstyle 元素中的內容原樣返回,無(wú)需進(jìn)一步解析:

>>>
>>> parser.feed('<style type="text/css">#python { color: green }</style>')
Start tag: style
     attr: ('type', 'text/css')
Data     : #python { color: green }
End tag  : style

>>> parser.feed('<script type="text/javascript">'
...             'alert("<strong>hello!</strong>");</script>')
Start tag: script
     attr: ('type', 'text/javascript')
Data     : alert("<strong>hello!</strong>");
End tag  : script

解析注釋:

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

解析命名或數字形式的字符引用,并把他們轉換到正確的字符(注意:這 3 種轉義都是 '>' ):

>>>
>>> parser.feed('&gt;&#62;&#x3E;')
Named ent: >
Num ent  : >
Num ent  : >

填充不完整的塊給 feed() 執行,handle_data() 可能會(huì )多次調用(除非 convert_charrefs 被設置為 True ):

>>>
>>> for chunk in ['<sp', 'an>buff', 'ered ', 'text</s', 'pan>']:
...     parser.feed(chunk)
...
Start tag: span
Data     : buff
Data     : ered
Data     : text
End tag  : span

解析無(wú)效的 HTML (例如:未引用的屬性)也能正常運行:

>>>
>>> parser.feed('<p><a class=link href=#main>tag soup</p ></a>')
Start tag: p
Start tag: a
     attr: ('class', 'link')
     attr: ('href', '#main')
Data     : tag soup
End tag  : p
End tag  : a