Zanurkuj w Pythonie/Przetwarzanie HTML-a: Różnice pomiędzy wersjami

Usunięta treść Dodana treść
zamiana {{Nawigacja|Python|->{{Nawigacja|Zanurkuj w Pythonie| [[Python/->[[../
Piotr (dyskusja | edycje)
poprawki
Linia 1:
{{Podświetl|py}}
== Nurkujemy ==
 
Na comp.lang.python często można zobaczyć pytania w stylu „jak"jak można znaleźć wszystkie [nagłówki|/obrazki|/linki] w moim dokumencie HTML?”, „jak"jak mogę sparsować/przetłumaczyć/przerobić tekst mojego dokumentu HTML tak, aby zostawić tagiznaczniki w spokoju?" lub też “jak"jak mogę natychmiastowo dodać/usunąć/zacytować atrybuty z wszystkich tagówznaczników mojego dokumentu HTML?". Rozdział ten odpowiada na wszystkie te pytania.
 
Poniżej przedstawiono w dwóch częściach całkowicie działający program. Pierwsza część, <tt>{{Python/Src|BaseHTMLProcessor.py</tt>}} jest ogólnym narzędziem, które przetwarza pliki HTML przechodząc przez wszystkie tagiznaczniki i bloki tekstowe. Druga część, <tt>{{Python/Src|dialect.py</tt>}}, jest przykładem tego, jak wykorzystać <tt>{{Python/Src|BaseHTMLProcessor.py</tt>}}, aby przetłumaczyć tekst dokumentu HTML, lecz przy tym zostawiając tagiznaczniki w spokoju. Przeczytaj napisynotki dokumentacyjne i komentarze w celu zorientowania się, co się tutaj właściwie dzieje. Duża część tego kodu wygląda jak czarna magia, ponieważ nie jest oczywiste w jaki sposób dowolna z metod klasy jest wywoływana. Jednak nie martw się, wszystko zostanie wyjaśnione w odpowiednim czasie.
 
{{Python/Przykład
'''Przykład 8.1. <tt>BaseHTMLProcessor.py</tt>'''
|8.1|{{Python/Src|BaseHTMLProcessor.py}}
 
|tekst=
Możesz [http://diveintopython.org/download/diveintopython-examples-5.4.zip pobrać wszystkie przykłady użyte w tej książce], jeśli jeszcze tego nie zrobiłeś.
<nowiki>
from sgmllib import SGMLParser
import htmlentitydefs
class BaseHTMLProcessor(SGMLParser):
def reset(self):
# extenddodatek (calledwywoływane byprzez SGMLParser.__init__)
self.pieces = []
SGMLParser.reset(self)
def unknown_starttag(self, tag, attrs):
# calledwywoływane fordla eachkażdego startpoczątkowego tagznacznika
# attrs isjest alistą list ofkrotek (attratrybut, valuewartość) tuples
# e.gnp. fordla <nowiki><pre class="screen">, będziemy mieli tag="pre", attrs=[("class", "screen")]
# Chcielibyśmy zrekonstruować oryginalne znaczniki i atrybuty, ale
# Ideally we would like to reconstruct original tag and attributes, but
# może się zdarzyć, że umieścimy w cudzysłowach wartości, które nie były zacytowane
# we may end up quoting attribute values that weren't quoted in the source
# w źródle dokumentu, a także możemy zmienić rodzaj cudzysłowi w wartości danego atrybutu
# document, or we may change the type of quotes around the attribute value
# (singlepojedyncze tocudzysłowy doublelub quotespodwójne).
# NoteDodajmy, thatże improperlyniepoprawnie embeddedosadzony nonkod nie-HTML code-owy (likenp. client-sidekod JavascriptJavaScript)
# maymoże bezostać parsedźle incorrectlysparsowany byprzez theklasę ancestorbazową, causinga to spowoduje runtimebłąd scriptwykonania errorsskryptu.
# AllCały nonnie-HTML codemusi mustbyć beumieszczony enclosedw inkomentarzu HTML comment tags-a (<!-- codekod -->),
# toaby ensureparser thatzostawił itten willniezmieniony pass(korzystając through this parser unaltered (inz handle_comment).
strattrs = "".join([' %s="%s"' % (key, value) for key, value in attrs])
self.pieces.append("<%(tag)s%(strattrs)s>" % locals())
def unknown_endtag(self, tag):
# calledwywoływane fordla eachkażdego endznacznika tag,końcowego e.gnp. fordla </pre>, tag willbędzie berówny "pre"
# Rekonstruuje oryginalny znacznik końcowy w wyjściowym dokumencie
# Reconstruct the original end tag.
self.pieces.append("</%(tag)s>" % locals())
def handle_charref(self, ref):
# calledwywoływane forjest eachdla characterkażdego reference,odwołania e.gznakowego np. fordla "&#160;", ref willbędzie berówne "160"
# Reconstruct theRekonstruuje originaloryginalne characterodwołanie referenceznakowe.
self.pieces.append("&#%(ref)s;" % locals())
def handle_entityref(self, ref):
# calledwywoływane forjest eachdla entitykażdego reference,odwołania e.gdo encji np. fordla "&copy;", ref willbędzie berówne "copy"
# ReconstructRekonstruuje theoryginalne originalodwołanie entitydo referenceencji.
self.pieces.append("&%(ref)s" % locals())
# standardstandardowe encje HTML-a entities arezakończone closedśrednikiem; withpozostałe aencje semicolon;(encje otherspoza entitiesHTML-a) arenie not
if htmlentitydefs.entitydefs.has_key(ref):
self.pieces.append(";")
def handle_data(self, text):
# calledwywoływane fordla eachkażdego blockbloku ofczystego plainteksu text, inp.e. outside ofdla anydanych tagspoza anddowolnego
#znacznika, w których nie występują żadne odwołania znakowe, czy odwołania do encji.
# not containing any character or entity references
# Store thePrzechowuje originaldosłownie textoryginalny verbatimtekst.
self.pieces.append(text)
def handle_comment(self, text):
# calledwywoływane fordla eachkażdego HTMLkomentarza comment, e.gnp. <!-- insertwpis kod JavaScript Javascriptw codetym heremiejscu -->
# Reconstruct theRekonstruuje originaloryginalny commentkomentarz.
# Jest to szczególnie ważne, gdy dokument zawiera kod przeznaczony
# It is especially important that the source document enclose client-side
# codedla przeglądarki (likenp. kod Javascript) within comments so it canwewnątrz passkomentarza, throughdzięki thistemu
# parser może przejść przez ten kod bez zakłóceń;
# processor undisturbed; see comments in unknown_starttag for details.
# więcej szczegółów w komentarzu metody unknown_starttag.
self.pieces.append("<!--%(text)s-->" % locals())
def handle_pi(self, text):
# calledwywoływane fordla eachkażdej processinginstrukcji instruction,przetwarzania e.gnp. <?instruction>
# ReconstructRekonstruuje originaloryginalną processinginstrukcję instruction.przetwarzania
self.pieces.append("<?%(text)s>" % locals())
def handle_decl(self, text):
# calledwywoływane dla fordeklaracji thetypu DOCTYPEdokumentu, ifjeśli presentwystępuje, e.gnp.
# <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
# "http://www.w3.org/TR/html4/loose.dtd">
# Rekonstruuje oryginalną deklarację typu dokumentu
# Reconstruct original DOCTYPE
self.pieces.append("<!%(text)s>" % locals())
def output(self):
u"""ReturnZwraca processedprzetworzony HTML asjako apojedynczy singlełańcuch stringznaków"""
return "".join(self.pieces)
if __name__ == "__main__":
for k, v in globals().items():
print k, "=", v
</nowiki>
}}
{{Python/Przykład
'''Przykład 8.2. <tt>dialect.py</tt>'''
|8.2|{{Python/Src|dialect.py}}
 
|tekst=
<nowiki>
import re
Linia 240 ⟶ 246:
test("http://diveintopython.org/odbchelper_list.html")
</nowiki>
}}
 
Uruchamiając ten skrypt, przetłumaczymy Sekcję[http://diveintopython.org/odbchelper_list.html podrozdział 3.2], z książki [[..http:/Listy|„Listy”]/diveintopython.org "Dive Into Python"], na pozorowany szwedzki kuchmistrza z Muppetów, udawany język Elmer Fudda (z kreskówek Królik Bugs) i pozorowany język średnioangielski (luźno oparty na "Chaucer's The Canterbury Tales"). Jeśli spojrzyszspojrzymy na źródło HTML wyjściowej strony, zobaczyszzobaczymy, że tagiznaczniki i atrybuty zostały nietknięte, lecz tekst między tagamiznacznikami został „przetłumaczony”"przetłumaczony" na udawany język. Jeśli przyjrzyszprzyglądniemy się jeszcze bardziej, zobaczyszzobaczymy, że tylko tytuły i akapity zostały przetłumaczone. Przedstawione kody i wyniki działania programu zostały niezmienione.
'''Przykład 8.3. Wyjście z <tt>dialect.py</tt>'''
 
{{Python/Przykład
Uruchamiając ten skrypt, przetłumaczymy Sekcję 3.2, [[../Listy|„Listy”]] na pozorowany szwedzki kuchmistrza z Muppetów, udawany język Elmer Fudda (z kreskówek Królik Bugs) i pozorowany język średnioangielski (luźno oparty na Chaucer's The Canterbury Tales). Jeśli spojrzysz na źródło HTML wyjściowej strony, zobaczysz, że tagi i atrybuty zostały nietknięte, lecz tekst między tagami został „przetłumaczony” na udawany język. Jeśli przyjrzysz się bardziej, zobaczysz, że tylko tytuły i akapity zostały przetłumaczone. Przedstawione kody i wyniki działania programu zostały niezmienione.
|8.3|Wyjście z {{Python/Src|dialect.py}}
|tekst=
 
{{samp|<nowiki><div class="abstract">
<p>Lists awe <span class="application">Pydon</span>'s wowkhowse datatype.
<div class="abstract">
If youw onwy expewience wif wists is awways in
<p>Lists awe <span class="application">Pydon</span>'s wowkhowse datatype.
<span class="application">PydonVisuaw Basic</span> wists.</p>ow (God fowbid) de datastowe
If youw onwy expewience wif wists is awways in
in <span class="application">Visuaw BasicPowewbuiwdew</span>, ow (God fowbid)bwace deyouwsewf datastowefow
in <span class="application">PowewbuiwdewPydon</span>, bwace youwsewf fowwists.</p>
</div></nowiki>}}
<span class="application">Pydon</span> wists.</p>
}}
</div>
</nowiki>
 
<noinclude>
Linia 260 ⟶ 268:
[[../Wprowadzenie do sgmllib.py|Wprowadzenie do <tt>sgmllib.py</tt>]]|
}}
{{Podświetl|py}}
</noinclude>