html.parser — Enkel HTML- och XHTML-parser

Källkod: Lib/html/parser.py


Den här modulen definierar en klass HTMLParser som fungerar som bas för parsning av textfiler formaterade i HTML (HyperText Mark-up Language) och XHTML.

class html.parser.HTMLParser(*, convert_charrefs=True)

Skapa en parserinstans som kan parsa ogiltig markup.

Om convert_charrefs är True (standard) konverteras alla teckenreferenser (utom de i cript/style-element) automatiskt till motsvarande Unicode-tecken.

En instans av HTMLParser matas med HTML-data och anropar hanteringsmetoder när starttaggar, sluttaggar, text, kommentarer och andra markeringselement påträffas. Användaren bör subklassa HTMLParser och åsidosätta dess metoder för att implementera önskat beteende.

Denna parser kontrollerar inte att sluttaggar matchar starttaggar eller anropar sluttagghanteraren för element som stängs implicit genom att stänga ett yttre element.

Ändrad i version 3.4: convert_charrefs nyckelordsargument tillagt.

Ändrad i version 3.5: Standardvärdet för argumentet convert_charrefs är nu True.

Exempel på HTML Parser-applikation

Som ett grundläggande exempel visas nedan en enkel HTML-parser som använder klassen HTMLParser för att skriva ut starttaggar, sluttaggar och data när de påträffas:

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

Utgången kommer då att vara:

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 Metoder

HTMLParser-instanser har följande metoder:

HTMLParser.feed(data)

Mata in text till parsern. Den bearbetas i den mån den består av fullständiga element; ofullständiga data buffras tills mer data matas in eller close() anropas. data måste vara str.

HTMLParser.close()

Tvingar fram bearbetning av alla buffrade data som om de följdes av en markering för slutet av filen. Denna metod kan omdefinieras av en härledd klass för att definiera ytterligare bearbetning i slutet av inmatningen, men den omdefinierade versionen bör alltid anropa basklassmetoden close() i HTMLParser.

HTMLParser.reset()

Återställer instansen. Förlorar alla obearbetade data. Detta anropas implicit vid instantieringstillfället.

HTMLParser.getpos()

Returnerar aktuellt radnummer och offset.

HTMLParser.get_starttag_text()

Returnerar texten i den senast öppnade starttaggen. Detta bör normalt inte behövas för strukturerad bearbetning, men kan vara användbart för att hantera HTML ”som den är distribuerad” eller för att återskapa indata med minimala ändringar (blanksteg mellan attribut kan bevaras etc.).

Följande metoder anropas när data- eller markeringselement påträffas och de är avsedda att åsidosättas i en underklass. Basklassens implementationer gör ingenting (förutom handle_startendtag()):

HTMLParser.handle_starttag(tag, attrs)

Denna metod anropas för att hantera starttaggen för ett element (t.ex. <div id="main">).

Argumentet tag är namnet på taggen konverterat till gemener. Argumentet attrs är en lista med paren (namn, värde) som innehåller de attribut som finns inom taggens <>-parenteser. name översätts till gemener och citattecken i value har tagits bort, och tecken- och entitetsreferenser har ersatts.

För taggen <A HREF="https://www.cwi.nl/"> skulle den här metoden till exempel anropas som handle_starttag('a', [('href', 'https://www.cwi.nl/')]).

Alla entitetsreferenser från html.entities ersätts i attributvärdena.

HTMLParser.handle_endtag(tag)

Denna metod anropas för att hantera sluttaggen för ett element (t.ex. </div>).

Argumentet tag är namnet på taggen konverterat till gemener.

HTMLParser.handle_startendtag(tag, attrs)

Liknar handle_starttag(), men anropas när parsern stöter på en tom tagg i XHTML-stil (<img ... />). Denna metod kan åsidosättas av underklasser som kräver denna speciella lexikala information; standardimplementationen anropar helt enkelt handle_starttag() och handle_endtag().

HTMLParser.handle_data(data)

Denna metod anropas för att bearbeta godtyckliga data (t.ex. textnoder och innehållet i .<script>.</script>. och .<style>.</style>.).

HTMLParser.handle_entityref(name)

Denna metod anropas för att behandla en namngiven teckenreferens av formen &name; (t.ex. &gt;), där name är en allmän entitetsreferens (t.ex. 'gt'). Denna metod anropas aldrig om convert_charrefs är True.

HTMLParser.handle_charref(name)

Denna metod anropas för att bearbeta decimala och hexadecimala numeriska teckenreferenser av formen &#NNN; och &#xNNN;. Exempelvis är den decimala motsvarigheten till &gt; &#62;, medan den hexadecimala är &#x3E;; i detta fall kommer metoden att ta emot '62' eller 'x3E'. Denna metod anropas aldrig om convert_charrefs är True.

HTMLParser.handle_comment(data)

Denna metod anropas när en kommentar påträffas (t.ex. <!--comment-->).

Exempelvis kommer kommentaren <!-- comment --> att leda till att denna metod anropas med argumentet ' comment '.

Innehållet i Internet Explorer villkorliga kommentarer (condcoms) kommer också att skickas till denna metod, så för <!--[om IE 9]>IE9-specifikt innehåll<![endif]--> kommer denna metod att få '[om IE 9]>IE9-specifikt innehåll<![endif]'.

HTMLParser.handle_decl(decl)

Denna metod anropas för att hantera en HTML-doktypdeklaration (t.ex. <!DOCTYPE html>).

Parametern decl kommer att vara hela innehållet i deklarationen inuti <!...>-markeringen (t.ex. 'DOCTYPE html').

HTMLParser.handle_pi(data)

Metod som anropas när en bearbetningsinstruktion påträffas. Parametern data kommer att innehålla hela bearbetningsinstruktionen. Till exempel, för bearbetningsinstruktionen <?proc color='red'>, skulle denna metod anropas som handle_pi("proc color='red'"). Den är avsedd att åsidosättas av en härledd klass; basklassens implementering gör ingenting.

Anteckning

Klassen HTMLParser använder SGML:s syntaktiska regler för bearbetningsinstruktioner. En XHTML-bearbetningsinstruktion som använder den efterföljande '?' kommer att leda till att '?' inkluderas i data.

HTMLParser.unknown_decl(data)

Denna metod anropas när en oigenkänd deklaration läses av parsern.

Parametern data kommer att vara hela innehållet i deklarationen inuti <![...]>-markeringen. Det är ibland användbart att åsidosättas av en härledd klass. Basklassens implementation gör ingenting.

Exempel

Följande klass implementerar en parser som kommer att användas för att illustrera fler exempel:

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

Parsning av en 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"

Parsning av ett element med några attribut och en titel:

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

Innehållet i elementen cript och style returneras som det är, utan ytterligare parsning:

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

Analyserar kommentarer:

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

Parsning av namngivna och numeriska teckenreferenser och konvertering av dem till rätt tecken (notera: dessa 3 referenser är alla likvärdiga med '>'):

>>> parser = MyHTMLParser()
>>> parser.feed('&gt;&#62;&#x3E;')
Data     : >>>

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

Att mata ofullständiga bitar till feed() fungerar, men handle_data() kan anropas mer än en gång (om inte convert_charrefs är satt till 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

Parsning av ogiltig HTML (t.ex. attribut som inte citeras) fungerar också:

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