Zanurkuj w Pythonie/Wprowadzenie do sgmllib.py
Wprowadzenie do sgmllib.py
[edytuj]Przetwarzanie HTML-a jest podzielone na trzy etapy: podzielenie dokumentu na elementy składowe, manipulowanie tymi elementami i ponowna rekonstrukcja tych kawałków do HTML-a. Pierwszy krok jest wykonywany przez sgmllib.py, który jest częścią standardowej biblioteki Pythona.
Kluczem do zrozumienia tego rozdziału jest uświadomienie sobie, że HTML to nie tylko tekst, jest to tekst z pewną strukturą. Struktura ta powstaje z mniej lub bardziej hierarchicznych sekwencji znaczników początkowych i znaczników końcowych. Zazwyczaj nie pracujemy z HTML-em w sposób strukturalny, raczej tekstowo w edytorze tekstu lub wizualnie w przeglądarce internetowej, czy innym narzędziu. sgmllib.py prezentuje HTML strukturalnie.
sgmllib.py zawiera jedną ważną klasę: SGMLParser
. SGMLParser
rozbiera HTML na użyteczne kawałki takie jak znaczniki początkowe i znaczniki końcowe. Jak tylko udaje mu się rozebrać jakieś dane na przydatne kawałki, wywołuję odpowiednią metodę, w zależności co zostało znalezione. Żeby wykorzystać parser, tworzymy podklasę SGMLParser
-a i nadpisujemy te metody. Mówiąc, że sgmllib.py prezentuje HTML strukturalnie, mieliśmy na myśli to, że struktura dokumentu HTML jest określana poprzez wywoływane metody, a także argumenty przekazywane do tych metod.
SGMLParser
parsuje HTML na 8 rodzajów danych i wykonuje odpowiednie metody dla każdego z nich:
- Znacznik początkowy
- Znacznik HTML, który rozpoczyna blok np. <html>, <head>, <body> lub <pre> lub samodzielne znaczniki jak <br> lub <img>. Kiedy odnajdzie znacznik tagname, to
SGMLParser
będzie szukał metod o nazwiestart_tagname
lubdo_tagname
. Na przykład, jeśli odnajdzie znacznik <pre>, to będzie szukał metodstart_pre
lubdo_pre
. Jeśli je znajdzie,SGMLParser
wywoła te metody z listą atrybutów tego znacznika. W przeciwnym wypadku wywołaunknown_starttag
z nazwą znacznika i listą atrybutów. - Znacznik końcowy
- Znacznik HTML, który kończy blok np. </html>, </head>, </body> lub </pre>. Kiedy odnajdzie znacznik końcowy,
SGMLParser
będzie szukał metody o nazwieend_tagname
. Jeśli ją znajdzie, wywoła tę metodę, jeśli nie, wywoła metodęunknown_endtag
z nazwą znacznika. - Odwołania znakowe
- Znak specjalny, do którego dowołujemy się podając jego dziesiętny lub szesnastkowy odpowiednik np.  . Kiedy odwołanie znakowe zostanie odnalezione,
SGMLParser
wywołahandle_charref
z tekstem dziesiętnego lub szesnastkowego odpowiednika znaku. - Odwołanie do encji
- Encja HTML to np. ©. Kiedy zostanie znaleziona,
SGMLParser
wywołujehandle_entityref
z nazwą encji. - Komentarz
- Element HTML, który jest ograniczony przez <!-- ... -->. Kiedy zostanie znaleziony,
SGMLParser
wywołujehandle_comment
z zawartością komentarza. - Instrukcje przetwarzania
- Instrukcje przetwarzania HTML są ograniczone przez <? ... >. Kiedy zostaną odnalezione,
SGMLParser
wywołujehandle_pi
z zawartością instrukcji przetwarzania. - Deklaracja
- Deklaracja HTML np. typu dokumentu (DOCTYPE), jest ograniczona przez <! ... >. Kiedy zostanie znaleziona,
SGMLParser
wywołujehandle_decl
z zawartością deklaracji. - Dane tekstowe
- Bloki tekstu. Wszystko inne, co się nie mieści w innych 7 kategoriach. Kiedy zostaną one znalezione,
SGMLParser
wywołahandle_data
z tekstem.
sgmllib.py posiada zestaw testów, które to ilustrują. Możemy uruchomić sgmllib.py, podając w linii poleceń nazwę pliku, a będzie on wyświetlał znaczniki i inne elementy podczas parsowania. Zrobione jest to poprzez utworzenie podklasy SGMLParser
i zdefiniowanie metod unknown_starttag
, unknown_endtag
, handle_data
i innych metod, które będą po prostu wyświetlać swoje argumenty.
W ActivePython IDE pod Windows możemy określić argumenty linii poleceń za pomocą "Run script". Różne argumenty oddzielamy spacją. |
c:\python23\lib> type "c:\downloads\diveintopython\html\toc\index.html" <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> <html lang="en"> <head> <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"> <title>Dive Into Python</title> <link rel="stylesheet" href="diveintopython.css" type="text/css"> [...ciach...]
Tutaj jest kawałek spisu treści angielskiej wersji tej książki, w HTML-u. Oczywiście ścieżki do plików możesz mieć trochę inne. (Angielską wersję tej książki, w formacie HTML, możesz znaleźć na http://diveintopython.org/.)
Uruchomiając to za pomocą zestawu testów sgmllib.py, zobaczymy:
c:\python23\lib> python sgmllib.py "c:\downloads\diveintopython\html\toc\index.html"
data: '\n\n' start tag: <html lang="en" > data: '\n ' start tag: <head> data: '\n ' start tag: <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1" > data: '\n \n ' start tag: <title> data: 'Dive Into Python' end tag: </title> data: '\n ' start tag: <link rel="stylesheet" href="diveintopython.css" type="text/css" > data: '\n ' [...ciach...]
Taki jest plan reszty tego rozdziału:
- Dziedziczymy po
SGMLParser
, aby stworzyć klasy, które wydobywają interesujące dane z dokumentu HTML. - Dziedziczymy po
SGMLParser
, aby stworzyć podklasęBaseHTMLProcessor
, która nadpisuje wszystkie 8 metod obsługi i wykorzystujemy je, aby zrekonstruować oryginalny dokument HTML z otrzymywanych kawałków. - Dziedziczymy po
BaseHTMLProcessor
, aby utworzyćDialectizer
, który dodaje kilka metod w celu specjalnego przetworzenia określonych znaczników HTML. Ponadto nadpisuje metodęhandle_data
, aby zapewnić możliwość przetwarzania bloków tekstowych pomiędzy znacznikami HTML. - Dziedziczymy po
Dialectizer
, aby stworzyć klasy, które definiują zasady przetwarzania tekstu wykorzystane wDialectizer.handle_data
. - Piszemy zestaw testów, które korzystają z prawdziwej strony internetowej, http://diveintopython.org/, i ją przetwarzają.
Przy okazji dowiemy się, czym jest locals
i globals
, a także jak formatować łańcuchy znaków za pomocą słowników.