1. 程式人生 > >html.parser - 簡單的HTML和XHTML 解析器

html.parser - 簡單的HTML和XHTML 解析器

 該模組定義了一個名為 HTMLParser的類,用於解析html和xhml格式的文字檔案

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

建立一個解析器例項來解析無用的標記

convert_charrefs (該引數預設是True )為True時,所有字元引用(指令碼/樣式元素除外)都會自動轉換為相應的Unicode字元

當遇到開始標籤、結束標籤,文字,註釋和其他標記元素時,HTMLParser例項將呼叫處理方法處理HTML資料,讀者應該繼承HTMLParser類並重寫它的方法來實現自己想要的解析方式

這個解析器不檢查結束標籤是否與開始標籤匹配,或者通過關閉外部元素來隱式素呼叫結束標記處理方法

程式示例

下面是一個簡單的示例,使用HTMLParser 類來輸出開始標籤,結束標籤和資料

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.feed(data)

將一些文字資料提供給解析器。只要其由完整的元素組成就能被處理;快取不完整的資料,直到輸入更多資料或者呼叫close()。資料必須是str型別

HTMLParser.close()

強制處理所有的緩衝資料,就像這些資料後面有一個檔案結束符一樣;該方法可以由派生類重新定義,以在輸入的末尾定義附加處理,但重新定義的版本應始終呼叫HTMLParser基類方法的close()

HTMLParser.reset()

重置例項。丟失所有未處理的資料,這在例項化時隱式呼叫。

HTMLParser.getpos()

返回當前行號和偏移量

HTMLParser.get_starttag_text()

返回最近開啟的開始標籤的文字。結構化處理通常不需要這樣做,但在處理HTML“部署”或重新生成具有最小更改的輸入(可以保留屬性之間的空白等)時可能很有用。

 

遇到資料或標記元素時會呼叫以下方法,並且要在子類中重新他們,基類中的實現什麼都不做(handle_startendtag()除外)

HTMLParser.handle_starttag(tag, attrs)

該方法處理開始標籤時呼叫(例如 <div id="main">

tag引數是轉換為小寫的標籤名稱

attrs引數是(name, vaule)對的列表,包含在標籤的<>內的熟悉

name被轉為小寫,並刪除值中的引號,並且已替換字元和實體引用

例如 對於標籤<A HREF="https://www.cwi.nl/"> 方法將會handle_starttag('a', [('href', 'https://www.cwi.nl/')])來處理

來著html.entities的所有實體引用都將替換為屬性值

HTMLParser.handle_endtag(tag)

該方法處理結束標籤 例如</div>

tag引數是轉換為小寫的標籤名稱

HTMLParser.handle_startendtag(tag, attrs)

和函式 HTMLParser.handle_starttag() 相似,但是當解析器遇到一個 XHTML格式的空標籤時(<img .../>),該方法可能需要子類重寫,當需要特定的詞彙資訊,預設實現只調用handler_starttag()和handler_endtag()

HTMLParser.handle_data(data)

呼叫該方法來處理任意資料(文字節點和<script>...</script> 和 <style>...</style>中的內容

HTMLParser.handle_entityref(name)

呼叫此方法來處理表單和名稱的命名字元引用;(&gt)其中name是一般實體引用()如果convert_charrefs為True 該方法永遠不會被呼叫

HTMLParser.handle_charref(name)

呼叫此方法來處理形式為&#NNN的十進位制和十六進位制數字字元引用&#xNNN.例如,&gt;的十進位制等效值是&#62,而十六進位制是&#x3E;在這種情況下,該方法將接收'62'或'x3E'。

HTMLParser.handle_comment(data)

遇到註釋時會呼叫此方法(<!--comment-->)

例如,註釋<!—-comment-—>將導致使用引數'comment'呼叫此方法
Internet Explorer條件註釋(condcoms)的內容也將傳送到此方法,因此,對於<! - [if IE 9]> IE9特定內容<![endif] - >,此方法將收到'[如果IE 9]> IE9特定內容<![endif]'。

HTMLParser.handle_decl(decl)

呼叫此方法來處理HTML doctype宣告(例如<!DOCTYPE html>)。
decl引數將是<!...>標記內宣告的全部內容(例如'DOCTYPE html')

HTMLParser.handle_pi(data)

遇到處理指令時呼叫此方法。data引數將包含整個處理指令。例如,對於處理指令<?proc color ='red'>,此方法將被呼叫handle_pi("proc color ='red'")

HTMLParser.unknown_decl(data)

當解析器讀取無法識別的宣告時,將呼叫此方法。
data引數將是<![...]>標記內宣告的全部內容。由派生類重寫有時很有用。

以下類實現了一個解析器

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

解析doctype

>>> 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"

解析具有一些屬性和標題的元素

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

指令碼和樣式元素的內容按原樣返回,無需進一步解析

>>> 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]

解析命名和數字字元引用並將它們轉換為正確的char(注意:這3個引用都等同於'>')

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

將不完整的塊提供給feed()可以工作,但handle_data()可能會被多次呼叫:

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

解析無效的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