It og informationssøgning Forelæsning 11 29. november 2006 Jakob Grue Simonsen Hypertekst og Python Andersen & Simonsen: kap. 12 I dag gennemgås materiale af uhyre praktisk (og kun i lidet omfang generel) karakter: Anvendelse af pythons indbyggede biblioteker til håndtering af hypertekst, eksemplificeret ved den nuværende standard for hypertekst, nemlig HyperText Markup Language (html). 1
Læringsmål I forventes efter egen læsning og indeværende forelæsning, at: Kende til strukturen af et html-dokument (hoved, krop). Kende til strukturen af tags, herunder særlige tags som omslutter hyperreferencer o. lign. Være bekendt med og kunne anvende enkelte af pythons standardbiblioteker til hentning af dokumenter på WWW, til parsing af HTML-dokumenter. 2
Generelt Hypertekst er (blødt!) en benævnelse for en særlig type brugergrænseflade til fremvisning af dokumenter, som kan udføre handlinger efter særlige forespørgsler. Forespørgsel forstås her i meget bred forstand. Et museklik på fremhævet tekst regnes for en forespørgsel om at se den tekst, som den fremhævede tekst refererer til. Den nuværende standard for hypertekst er HTML; vi gennemgår kort dokumentstrukturen i det følgende. Hypertekst fortolkes på en given maskine af en særlig fortolker (kaldet en browser ); f.eks. MS Internet Explorer. 3
Strukturen af et HTML-dokument et dokument i HTML indledes af en versionsangivelse, følges af et hoved (typisk med metadata for dokumentet: Titel o.lign.), og dernæst af en krop. De forskellige dele af dokumentet omsluttes af såkaldte tags (eksempel nedenfor). <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/tr/html4/strict.dtd"> <html> <head> <title>uddrag af "Mads Doss"</title> </head> <body> Mett Kølvro war en kon stonthostøs </body> </html> 4
Tags metainformation Tags anvendes i både hoved og krop til at angive metainformation om teksten (fremhævelse, hyperreferencer o. lign.). Hovedparten af tags forekommer parvis. F.eks.: <title>, hhv. </title> <h1>, hhv. </h1> <p>, </p> <em>, </em> strong hhv. hhv. Omslutter dokumentets titel. skal forekomme i dokumentets hoved. Omslutter en overskrift, der således fremhæves. <h2> <h6> har samme betydning, men giver successivt mindre fremhævelse Indleder, hhv. afslutter et afsnit i teksten (passende linjeskift indsættes automatisk). </p> kan principielt udelades; dette anses for sjusk. Omgiver fremhævet (typisk ved kursivering) tekst. 5
Hyperreferencer En hyperreference er et særligt udsnit af teksten i et dokument, der henviser til en del af en (muligvis anden) tekst. En typisk forespørgsel (museklik) vil bede fortolkeren om at hente og fremvise teksten. Man kan f.eks. lave henvisninger til andetsteds i samme dokument, til andre lokale dokumenter, eller til dokumenter andre steder på internettet vha. disses addresse, den såkaldte Uniform Resource Locator (URL): Dette er en hægte til <a href="http://www.w3.org/"> W3C </a> Bemærk de tilhørende tags. 6
Kommentarer Som med python er HTML et formelt sprog (in casu et meget lidt kraftfuldt programmeringssprog). Adskillige strukturer kendt fra python forefindes således tillige i HTML, herunder kommentarer dog med en anden syntaks. <!-- Dette er en kommentar; den vises ikke af en browser. Husk, at både i HTML og i Python er det en dyd at skrive informative, koncise kommentarer --> 7
Behandling af HTML-dokumenter i python Vi ønsker at benytte pythons indbyggede biblioteker til at behandle HTML-dokumenter. Oplagte muligheder er at skrælle alle HTML-konstruktioner væk (og dermed stå tilbage med den rå tekst, som dokumentet indeholder), eller at holde styr på indlejrede tags (for at fremvise dokumentet korrekt). Biblioteket HTMLParser er velegnet til begge dele. Skrælning: >>>import HTMLParser >>>class DataStripper(HTMLParser.HTMLParser): >>> def handle_data(self,data): >>> if data.strip(): >>> print(data) >>> 8
Skrælning fortsat Bemærk: Vi erklærer en klasse, der nedarver fra klassen HTMLParser.HTMLParser. Dermed får vi adgang til alle metoder fra HTMLParser, men kan frit udvide med ny metoder efter behov (f.eks. i metoden handle data ovenfor. data.strip er en særlig indbygget metode, som fjerner al meta-information, tags o.lign, og kun medtager oprindelige linjeskift i dokumentet. 9
Mere om skrælning Tag nu et banalt dokument i HTML: htmltekst = """ <html> <head> <title> Et velment råd </title> </head> <body> <p> <a href="http://www.yuni.com/library/latin_8.html">dixit vir prudens:</ <em>non contra ventum minge!</em></a></p> </body> </html> """ (Hvor vi frækt har udeladt versionsangivelsen). Et kald af den indbyggede metode feed i klassen DataStripper som jo nedarvede fra HTMLParser.HTMLParser afstedkommer nu, at data.strip bliver kaldt på ovenstående tekst: >>>DataStripper().feed(htmltekst) Et velment råd Dixit vir prudens: Non contra ventum minge! 10
Stakbaseret parsing Som et, lidt sværere, eksempel viser vi, hvordan man kan holde styr på indlejringen af tags i et HTML-dokument ved at benytte såkaldt stakbaseret parsing (se tavlen for at se, hvordan stakke kommer ind i billedet). Som med skrælning benytter vi os af tricket med at nedarve fra HTMLParser.HTMLParser. tagstak = [] import HTMLParser class VisStruktur(HTMLParser.HTMLParser): def handle_starttag(self, tag, attributter): tagstak.append(tag) def handle_endtag(self, tag): tagstak.pop() def handle_data(self, data): for tag in tagstak: sys.stdout.write( / +tag) sys.stdout.write(": %s \n" % data) Bemærk de tre indbyggede metoder handle.... 11
Stakbaseret parsing fortsat Et kald >>> VisStruktur().feed(htmltekst) Resulterer dernæst i følgende uddata: /html/body/p/html/body: /html/body/p/html/body/html: /html/body/p/html/body/html/head: /html/body/p/html/body/html/head/title: Et velment råd /html/body/p/html/body/html/head: /html/body/p/html/body/html: /html/body/p/html/body/html/body: /html/body/p/html/body/html/body/p: /html/body/p/html/body/html/body/p/a: Dixit vir prudens: /html/body/p/html/body/html/body/p: /html/body/p/html/body/html/body/p/em: Non contra ventum minge! /html/body/p/html/body/html: /html/body/p/html/body: /html/body/p/html: Bemærk, hvorledes indlejringsstrukturen af de forskellige tags dermed gøres eksplicit. 12
Hente dokumenter på internettet HTML-dokumenter kan hentes manuelt ved hjælp af en browser, men det er ved hentning af større tekstkorpora (f.eks. sådanne, hvor tekstnavnene og deres lokationer URLer er givet ved en liste) snedigere at lade python hente dokumenterne automatisk. En let måde at gøre dette på er ved biblioteket httplib. Essentielt skal man blot angive en adresse, og lade programmet hente dokumentet på adressen: >>> from httplib import HTTP >>> foresp = HTTP("cst.dk") >>> foresp.putrequest("get", "/index.html") >>> foresp.putheader("accept", "text/html") >>> foresp.putheader("user-agent", "MitProgram") >>> foresp.endheaders() >>> >>> fk, fm, h = foresp.getreply() >>> print fk, fm 200 OK >>> >>> doku = foresp.getfile() >>> tekst = doku.read() >>> doku.close() >>> >>> print tekst <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/tr/htm <html> <head> Store mængder tekst </div> </body> </html> 13
Tak for i dag Husk at se på opgaverne til på fredag! 14