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) defhandle_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)
呼叫此方法來處理表單和名稱的命名字元引用;(>)其中name是一般實體引用()如果convert_charrefs為True 該方法永遠不會被呼叫
HTMLParser.handle_charref(name)
呼叫此方法來處理形式為&#NNN的十進位制和十六進位制數字字元引用&#xNNN.例如,&gt;的十進位制等效值是>,而十六進位制是>在這種情況下,該方法將接收'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('>>>') 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