# `html.parser` — Simple HTML and XHTML parser

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 `script` e `style`) serão convertidas automaticamente para os caracteres Unicode correspondentes.

  Se scripting for falso (o padrão), o conteúdo do elemento `noscript` será analisado normalmente; se for verdadeiro, será retornado como está, sem ser analisado.

  Uma instância de `HTMLParser` recebe 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 de `HTMLParser` e 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.10.20: 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("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>')

A saída então será:

    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

## 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 tipo `str`.

`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 base `HTMLParser`.

`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 como `handle_starttag('a', [('href', 'https://www.cwi.nl/')])`.

  Todas as referências de entidade de `html.entities` sã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 chama `handle_starttag()` e `handle_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 `script` e `style`).

`HTMLParser.``handle_entityref`(name)

  Este método é chamado para processar uma referência de caractere nomeada no formato `&name;` (por exemplo, `&gt;`), 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)

  This method is called to process decimal and hexadecimal numeric character references of the form `&#NNN;` and `&#xNNN;`. For example, the decimal equivalent for `&gt;` is `&#62;`, whereas the hexadecimal is `&#x3E;`; in this case the method will receive `'62'` or `'x3E'`. This method is only called if convert_charrefs is false.

`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 como `handle_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 `HTMLParser` usa 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()

Analisando um 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"

Analisando um elemento com alguns atributos e um título:

    >>> 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

O conteúdo de elementos como `script` e `style` é retornado como está, sem mais análises:

    >>> 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! &#9786;</strong>");</script>')
    Start tag: script
         attr: ('type', 'text/javascript')
    Data     : alert("<strong>hello! &#9786;</strong>");
    End tag  : script

Analisando comentários:

    >>> parser.feed('<!-- a comment -->'
    ...             '<!--[if IE 9]>IE-specific content<![endif]-->')
    Comment  :  a comment
    Comment  : [if IE 9]>IE-specific content<![endif]

Analisando referências de caracteres nomeadas e numéricas e convertendo-as para o caractere correto (nota: essas 3 referências são todas equivalentes a `'>'`):

    >>> parser.feed('&gt;&#62;&#x3E;')
    Named ent: >
    Num ent  : >
    Num ent  : >

Alimentar o `feed()` com blocos incompletos funciona, mas `handle_data()` pode ser chamado mais de uma vez se convert_charrefs for falso.

    >>> 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

Analisando HTML inválido (por exemplo, atributos sem aspas) também funciona:

    >>> 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