20.2。 html.parser
- 简单的HTML和XHTML解析器¶
此模块定义了一个类HTMLParser
,作为解析以HTML(超文本标记语言)和XHTML格式化的文本文件的基础。
- class
html.parser.
HTMLParser
(*, convert_charrefs=True)¶ 创建一个解析器实例能够解析无效标记。
如果convert_charrefs是
True
(默认值),所有字符引用(script
/style
会自动转换为相应的Unicode字符。当遇到开始标签,结束标签,文本,注释和其他标记元素时,
HTMLParser
实例提供HTML数据并调用处理程序方法。用户应该子类化HTMLParser
并覆盖其方法以实现所需的行为。此解析器不检查结束标记是否匹配开始标记,或者通过关闭外部元素来隐式关闭的元素调用结束标记处理程序。
在版本3.4中已更改: convert_charrefs添加了关键字参数。
在版本3.5中更改:参数convert_charrefs的默认值现在为
True
。
20.2.1. Example HTML Parser Application¶
作为一个基本示例,下面是一个简单的HTML解析器,它使用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
20.2.2. HTMLParser
Methods¶
HTMLParser
实例具有以下方法:
-
HTMLParser.
close
()¶ 强制处理所有缓冲的数据,就好像它后面是文件结束标记。此方法可以由派生类重新定义,以在输入结束时定义附加处理,但重新定义的版本应始终调用
HTMLParser
基类方法close()
。
-
HTMLParser.
reset
()¶ 重置实例。丢失所有未处理的数据。这在实例化时隐式调用。
-
HTMLParser.
getpos
()¶ 返回当前行号和偏移量。
-
HTMLParser.
get_starttag_text
()¶ 返回最近打开的开始标记的文本。这通常不需要用于结构化处理,但是可能在处理“部署的”或用于以最小改变重新生成输入(可以保留属性之间的空格等)时有用。)。
当遇到数据或标记元素并且它们意图在子类中被覆盖时,调用以下方法。基类实现什么也不做(除了handle_startendtag()
):
-
HTMLParser.
handle_starttag
(tag, attrs)¶ 调用此方法来处理标记的开始(例如,
&lt; div id =“main”&gt;
)。标签参数是转换为小写的标签的名称。The attrs argument is a list of
(name, value)
pairs containing the attributes found inside the tag’s<>
brackets. 名称将转换为小写,值中的引号已删除,字符和实体引用已替换。对于实例,对于标签
&lt; A HREF =“https://www.cwi.nl/”&gt;
称为handle_starttag('a', [('href', 'https://www.cwi.nl/')])
。来自
html.entities
的所有实体引用都将在属性值中替换。
-
HTMLParser.
handle_endtag
(tag)¶ 调用此方法来处理元素的结束标记(例如,
</div>
)。标签参数是转换为小写的标签的名称。
-
HTMLParser.
handle_startendtag
(tag, attrs)¶ Similar to
handle_starttag()
, but called when the parser encounters an XHTML-style empty tag (<img ... />
). 这个方法可以被需要这个特定词汇信息的子类覆盖;默认实现只需调用handle_starttag()
和handle_endtag()
。
-
HTMLParser.
handle_data
(data)¶ 调用此方法来处理任意数据(例如,文本节点和
<script>...</script>
和<style>...</style>
)的内容。
-
HTMLParser.
handle_entityref
(name)¶ 调用此方法来处理形式为
&name;
的命名字符引用(例如,>
),其中name是一般实体引用'gt'
)。如果convert_charrefs为True
,则不会调用此方法。
-
HTMLParser.
handle_charref
(name)¶ 调用此方法以处理形式为
&#NNN;
和&#xNNN;
的十进制和十六进制数字字符引用。例如,>
的十进制等于>
,而十六进制是>
;在这种情况下,该方法将接收'62'
或'x3E'
。如果convert_charrefs为True
,则不会调用此方法。
-
HTMLParser.
handle_comment
(data)¶ 当遇到注释时调用此方法。
<!--comment-->
)。例如,注释
注释 - >
将导致调用此方法与参数' 注释 '
。The content of Internet Explorer conditional comments (condcoms) will also be sent to this method, so, for
<!--[if IE 9]>IE9-specific content<![endif]-->
, this method will receive'[if IE 9]>IE9-specific content<![endif]'
.
-
HTMLParser.
handle_decl
(decl)¶ 调用此方法来处理HTML doctype声明。
&lt;!DOCTYPE html&gt;
)。decl t>参数将是
<!...>
标记内声明的全部内容。'DOCTYPE html'
)。
-
HTMLParser.
handle_pi
(data)¶ 遇到处理指令时调用的方法。数据参数将包含整个处理指令。For example, for the processing instruction
<?proc color='red'>
, this method would be called ashandle_pi("proc color='red'")
. 它的目的是被一个派生类覆盖;基类实现什么也不做。注意
HTMLParser
类使用SGML语法规则来处理指令。使用尾随'?'
的XHTML处理指令将导致'?'
以包括在数据中。
-
HTMLParser.
unknown_decl
(data)¶ 当解析器读取无法识别的声明时,将调用此方法。
data参数将是
<![...]>
标记内声明的全部内容。有时有用的是被派生类覆盖。基类实现什么也不做。
20.2.3. Examples¶
下面的类实现了一个解析器,将用来说明更多的例子:
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
script
和style
元素的内容按原样返回,无需进一步解析:
>>> 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()
可能会被调用多次(除非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
解析无效的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