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

猜你喜欢

转载自www.cnblogs.com/nixiaocang/p/10217454.html