html.parser — Analisador simples de HTML e XHTML¶
Código-fonte: Lib/html/parser.py
Este módulo define uma classe HTMLParser que serve como base para analisar arquivos de texto formatados em HTML (HyperText Markup Language) e XHTML.
- class html.parser.HTMLParser(*, convert_charrefs=True, scripting=False)¶
Cria uma instância de analisador sintático capaz de analisar marcação inválida.
Se convert_charrefs for verdadeiro (o padrão), todas as referências de caracteres (exceto as de elementos como
scriptestyle) serão convertidas automaticamente para os caracteres Unicode correspondentes.Se scripting for falso (o padrão), o conteúdo do elemento
noscriptserá analisado normalmente; se for verdadeiro, será retornado como está, sem ser analisado.Uma instância de
HTMLParserrecebe dados HTML e chama métodos de tratamento quando encontra tags de abertura, tags de fechamento, texto, comentários e outros elementos de marcação. O usuário deve criar uma subclasse deHTMLParsere substituir seus métodos para implementar o comportamento desejado.Este analisador sintático não verifica se as tags de fechamento correspondem às tags de abertura nem chama o manipulador de tags de fechamento para elementos que são fechados implicitamente pelo fechamento de um elemento externo.
Alterado na versão 3.4: Adicionado o argumento nomeado convert_charrefs.
Alterado na versão 3.5: O valor padrão para o argumento convert_charrefs agora é
True.Alterado na versão 3.14.1: Adicionado o parâmetro scripting.
Exemplo de aplicação para análise de HTML¶
Como exemplo básico, abaixo está um analisador HTML simples que usa a classe HTMLParser para exibir as tags de abertura, tags de fechamento e dados à medida que são encontrados:
from html.parser import HTMLParser
class MyHTMLParser(HTMLParser):
def handle_starttag(self, tag, attrs):
print("Encontrada a tag de abertura :", tag)
def handle_endtag(self, tag):
print("Encontrada a tag de fechamento:", tag)
def handle_data(self, data):
print("Encontrados alguns dados :", data)
parser = MyHTMLParser()
parser.feed('<html><head><title>Teste</title></head>'
'<body><h1>Me analise!</h1></body></html>')
A saída então será:
Encontrada a tag de abertura : html
Encontrada a tag de abertura : head
Encontrada a tag de abertura : title
Encontrados alguns dados : Teste
Encontrada a tag de fechamento: title
Encontrada a tag de fechamento: head
Encontrada a tag de abertura : body
Encontrada a tag de abertura : h1
Encontrados alguns dados : Me analise!
Encontrada a tag de fechamento: h1
Encontrada a tag de fechamento: body
Encontrada a tag de fechamento: html
Métodos HTMLParser¶
Instâncias de HTMLParser têm os seguintes métodos:
- HTMLParser.feed(data)¶
Fornece algum texto ao analisador. Ele será processado na medida em que consistir em elementos completos; dados incompletos serão armazenados em buffer até que mais dados sejam fornecidos ou que o método
close()seja chamado. Os dados devem ser do tipostr.
- HTMLParser.close()¶
Força o processamento de todos os dados em buffer como se fossem seguidos por uma marca de fim de arquivo. Este método pode ser redefinido por uma classe derivada para definir processamento adicional no final da entrada, mas a versão redefinida deve sempre chamar o método
close()da classe baseHTMLParser.
- HTMLParser.reset()¶
Reinicializa a instância. Perde todos os dados não processados. Este método é chamado implicitamente no momento da instanciação.
- HTMLParser.getpos()¶
Retorna o número da linha atual e o deslocamento.
- HTMLParser.get_starttag_text()¶
Retorna o texto da tag de abertura aberta mais recentemente. Normalmente, isso não é necessário para processamento estruturado, mas pode ser útil ao lidar com HTML “como implantado” ou para regenerar a entrada com alterações mínimas (o espaço em branco entre os atributos pode ser preservado, etc.).
Os seguintes métodos são chamados quando elementos de dados ou de marcação são encontrados e devem ser sobrescritos em uma subclasse. As implementações da classe base não fazem nada (exceto por handle_startendtag()):
- HTMLParser.handle_starttag(tag, attrs)¶
Este método é chamado para manipular a tag de abertura de um elemento (por exemplo,
<div id="main">).O argumento tag é o nome da tag convertido para minúsculas. O argumento attrs é uma lista de pares
(nome, valor)contendo os atributos encontrados dentro dos colchetes<>da tag. O nome será traduzido para minúsculas, as aspas no valor foram removidas e as referências a caracteres e entidades foram substituídas.Por exemplo, para a tag
<A HREF="https://www.cwi.nl/">, este método seria chamado comohandle_starttag('a', [('href', 'https://www.cwi.nl/')]).Todas as referências de entidade de
html.entitiessão substituídas nos valores dos atributos.
- HTMLParser.handle_endtag(tag)¶
Este método é chamado para manipular a tag de fechamento de um elemento (por exemplo,
</div>).O argumento tag é o nome da etiqueta convertido para letras minúsculas.
- HTMLParser.handle_startendtag(tag, attrs)¶
Similar a
handle_starttag(), mas chamado quando o analisador sintático encontra uma tag vazia no estilo XHTML (<img ... />). Este método pode ser substituído por subclasses que requerem essa informação lexical específica; a implementação padrão simplesmente chamahandle_starttag()ehandle_endtag().
- HTMLParser.handle_data(data)¶
Este método é chamado para processar dados arbitrários (por exemplo, nós de texto e o conteúdo de elementos como
scriptestyle).
- HTMLParser.handle_entityref(name)¶
Este método é chamado para processar uma referência de caractere nomeada no formato
&name;(por exemplo,>), onde name é uma referência de entidade genérica (por exemplo,'gt'). Este método só é chamado se convert_charrefs for falso.
- HTMLParser.handle_charref(name)¶
Este método é chamado para processar referências de caracteres numéricos decimais e hexadecimais no formato
&#NNN;e&#xNNN;. Por exemplo, o equivalente decimal para>é>, enquanto o hexadecimal é>; neste caso, o método receberá'62'ou'x3E'. Este método só é chamado se convert_charrefs for falso.
- HTMLParser.handle_comment(data)¶
Este método é chamado quando um comentário é encontrado (por exemplo,
<!--comentário-->).Por exemplo, o comentário
<!-- comentário -->fará com que este método seja chamado com o argumento' comentário '.O conteúdo dos comentários condicionais do Internet Explorer (condcoms) também será enviado para este método, portanto, para
<!--[if IE 9]>conteúdo específico do IE9<![endif]-->, este método receberá'[if IE 9]>conteúdo específico do IE9<![endif]'.
- HTMLParser.handle_decl(decl)¶
Este método é chamado para lidar com uma declaração de doctype HTML (por exemplo,
<!DOCTYPE html>).O parâmetro decl será todo o conteúdo da declaração dentro da marcação
<!...>(por exemplo,'DOCTYPE html').
- HTMLParser.handle_pi(data)¶
Método chamado quando uma instrução de processamento é encontrada. O parâmetro data conterá a instrução de processamento completa. Por exemplo, para a instrução de processamento
<?proc color='red'>, este método seria chamado comohandle_pi("proc color='red'"). Ele foi projetado para ser substituído por uma classe derivada; a implementação da classe base não faz nada.Nota
A classe
HTMLParserusa as regras sintáticas SGML para processar instruções. Uma instrução de processamento XHTML que usa o caractere'?'no final fará com que o'?'seja incluído em data.
- HTMLParser.unknown_decl(data)¶
Este método é chamado quando uma declaração não reconhecida é lida pelo analisador sintático.
O parâmetro data será todo o conteúdo da declaração dentro da marcação
<![...]>. Às vezes, é útil que ele seja sobrescrito por uma classe derivada. A implementação da classe base não faz nada.
Exemplos¶
A classe a seguir implementa um analisador sintático que será usado para ilustrar mais exemplos:
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()
Parsing a 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"
Parsing an element with a few attributes and a title:
>>> 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
The content of elements like script and style is returned as is,
without further parsing:
>>> 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
Parsing comments:
>>> parser.feed('<!--a comment-->'
... '<!--[if IE 9]>IE-specific content<![endif]-->')
Comment : a comment
Comment : [if IE 9]>IE-specific content<![endif]
Parsing named and numeric character references and converting them to the
correct char (note: these 3 references are all equivalent to '>'):
>>> parser = MyHTMLParser()
>>> parser.feed('>>>')
Data : >>>
>>> parser = MyHTMLParser(convert_charrefs=False)
>>> parser.feed('>>>')
Named ent: >
Num ent : >
Num ent : >
Feeding incomplete chunks to feed() works, but
handle_data() might be called more than once
if convert_charrefs is false:
>>> 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
Parsing invalid HTML (e.g. unquoted attributes) also works:
>>> 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