html.parser
--- 簡(jiǎn)單的 HTML 和 XHTML 解析器?
源代碼: Lib/html/parser.py
這個(gè)模塊定義了一個(gè) HTMLParser
類,為 HTML(超文本標(biāo)記語(yǔ)言)和 XHTML 文本文件解析提供基礎(chǔ)。
- class html.parser.HTMLParser(*, convert_charrefs=True)?
創(chuàng)建一個(gè)能解析無(wú)效標(biāo)記的解析器實(shí)例。
如果 convert_charrefs 為
True
(默認(rèn)值),則所有字符引用(script
/style
元素中的除外)都會(huì)自動(dòng)轉(zhuǎn)換為相應(yīng)的 Unicode 字符。一個(gè)
HTMLParser
類的實(shí)例用來(lái)接受 HTML 數(shù)據(jù),并在標(biāo)記開(kāi)始、標(biāo)記結(jié)束、文本、注釋和其他元素標(biāo)記出現(xiàn)的時(shí)候調(diào)用對(duì)應(yīng)的方法。要實(shí)現(xiàn)具體的行為,請(qǐng)使用HTMLParser
的子類并重載其方法。這個(gè)解析器不檢查結(jié)束標(biāo)記是否與開(kāi)始標(biāo)記匹配,也不會(huì)因外層元素完畢而隱式關(guān)閉了的元素引發(fā)結(jié)束標(biāo)記處理。
在 3.4 版更改: convert_charrefs 關(guān)鍵字參數(shù)被添加。
在 3.5 版更改: convert_charrefs 參數(shù)的默認(rèn)值現(xiàn)在為
True
。
HTML 解析器的示例程序?
下面是簡(jiǎn)單的 HTML 解析器的一個(gè)基本示例,使用 HTMLParser
類,當(dāng)遇到開(kāi)始標(biāo)記、結(jié)束標(biāo)記以及數(shù)據(jù)的時(shí)候?qū)?nèi)容打印出來(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)?
填充一些文本到解析器中。如果包含完整的元素,則被處理;如果數(shù)據(jù)不完整,將被緩沖直到更多的數(shù)據(jù)被填充,或者
close()
被調(diào)用。data 必須為str
類型。
- HTMLParser.close()?
如同后面跟著一個(gè)文件結(jié)束標(biāo)記一樣,強(qiáng)制處理所有緩沖數(shù)據(jù)。這個(gè)方法能被派生類重新定義,用于在輸入的末尾定義附加處理,但是重定義的版本應(yīng)當(dāng)始終調(diào)用基類
HTMLParser
的close()
方法。
- HTMLParser.reset()?
重置實(shí)例。丟失所有未處理的數(shù)據(jù)。在實(shí)例化階段被隱式調(diào)用。
- HTMLParser.getpos()?
返回當(dāng)前行號(hào)和偏移值。
- HTMLParser.get_starttag_text()?
返回最近打開(kāi)的開(kāi)始標(biāo)記中的文本。 結(jié)構(gòu)化處理時(shí)通常應(yīng)該不需要這個(gè),但在處理“已部署”的 HTML 或是在以最小改變來(lái)重新生成輸入時(shí)可能會(huì)有用處(例如可以保留屬性間的空格等)。
下列方法將在遇到數(shù)據(jù)或者標(biāo)記元素的時(shí)候被調(diào)用。他們需要在子類中重載?;惖膶?shí)現(xiàn)中沒(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 參數(shù)是小寫(xiě)的標(biāo)記名。attrs 參數(shù)是一個(gè)
(name, value)
形式的列表,包含了所有在標(biāo)記的<>
括號(hào)中找到的屬性。name 轉(zhuǎn)換為小寫(xiě),value 的引號(hào)被去除,字符和實(shí)體引用都會(huì)被替換。實(shí)例中,對(duì)于標(biāo)簽
<A >
,這個(gè)方法將以下列形式被調(diào)用handle_starttag('a', [('href', 'https://www.cwi.nl/')])
。html.entities
中的所有實(shí)體引用,會(huì)被替換為屬性值。
- HTMLParser.handle_endtag(tag)?
此方法被用來(lái)處理元素的結(jié)束標(biāo)記(例如:
</div>
)。tag 參數(shù)是小寫(xiě)的標(biāo)簽名。
- HTMLParser.handle_startendtag(tag, attrs)?
類似于
handle_starttag()
, 只是在解析器遇到 XHTML 樣式的空標(biāo)記時(shí)被調(diào)用(<img ... />
)。這個(gè)方法能被需要這種特殊詞法信息的子類重載;默認(rèn)實(shí)現(xiàn)僅簡(jiǎn)單調(diào)用handle_starttag()
和handle_endtag()
。
- HTMLParser.handle_data(data)?
這個(gè)方法被用來(lái)處理任意數(shù)據(jù)(例如:文本節(jié)點(diǎn)和
<script>...</script>
以及<style>...</style>
中的內(nèi)容)。
- HTMLParser.handle_entityref(name)?
這個(gè)方法被用于處理
&name;
形式的命名字符引用(例如>
),其中 name 是通用的實(shí)體引用(例如:'gt'
)。如果 convert_charrefs 為True
,該方法永遠(yuǎn)不會(huì)被調(diào)用。
- HTMLParser.handle_charref(name)?
這個(gè)方法被用來(lái)處理
&#NNN;
和&#xNNN;
形式的十進(jìn)制和十六進(jìn)制字符引用。例如,>
等效的十進(jìn)制形式為>
,而十六進(jìn)制形式為>
;在這種情況下,方法將收到'62'
或'x3E'
。如果 convert_charrefs 為True
,則該方法永遠(yuǎn)不會(huì)被調(diào)用。
- HTMLParser.handle_comment(data)?
這個(gè)方法在遇到注釋的時(shí)候被調(diào)用(例如:
<!--comment-->
)。例如,
<!-- comment -->
這個(gè)注釋會(huì)用' comment '
作為參數(shù)調(diào)用此方法。Internet Explorer 條件注釋(condcoms)的內(nèi)容也被發(fā)送到這個(gè)方法,因此,對(duì)于
<!--[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 形參為
<!...>
標(biāo)記中的所有內(nèi)容(例如:'DOCTYPE html'
)。
- HTMLParser.handle_pi(data)?
此方法在遇到處理指令的時(shí)候被調(diào)用。data 形參將包含整個(gè)處理指令。例如,對(duì)于處理指令
<?proc color='red'>
,這個(gè)方法將以handle_pi("proc color='red'")
形式被調(diào)用。它旨在被派生類重載;基類實(shí)現(xiàn)中無(wú)任何實(shí)際操作。備注
HTMLParser
類使用 SGML 語(yǔ)法規(guī)則處理指令。使用'?'
結(jié)尾的 XHTML 處理指令將導(dǎo)致'?'
包含在 data 中。
- HTMLParser.unknown_decl(data)?
當(dāng)解析器讀到無(wú)法識(shí)別的聲明時(shí),此方法被調(diào)用。
data 形參為
<![...]>
標(biāo)記中的所有內(nèi)容。某些時(shí)候?qū)ε缮惖闹剌d很有用?;悓?shí)現(xiàn)中無(wú)任何實(shí)際操作。
例子?
下面的類實(shí)現(xiàn)了一個(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è)文檔類型聲明:
>>> 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è)具有一些屬性和標(biāo)題的元素:
>>> 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
script
和 style
元素中的內(nèi)容原樣返回,無(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]
解析命名或數(shù)字形式的字符引用,并把他們轉(zhuǎn)換到正確的字符(注意:這 3 種轉(zhuǎn)義都是 '>'
):
>>> parser.feed('>>>')
Named ent: >
Num ent : >
Num ent : >
填充不完整的塊給 feed()
執(zhí)行,handle_data()
可能會(huì)多次調(diào)用(除非 convert_charrefs 被設(shè)置為 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 (例如:未引用的屬性)也能正常運(yùn)行:
>>> 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