Programmierkurs – Kapitel 4 Dipl.-Wirt.-Inf. Stefan Fleischer Dipl.-Wirt.-Inf. Ulrich Wolffgang Programmierkurs Komponente: Parser Interface für Parser entwickeln public interface IParser { public ArrayList<String> parseEmailAddresses(String content); public ArrayList<URL> parseUrls(String content); } Programmierkurs 1 Entwicklungsfolie für die Tafel WWW World Wide Web: über das Internet abrufbarer Hypertext 1989 am CERN von Berners-Lee erfunden Internet != WWW Drei Kernstandards HTTP als Protokoll HTML als Dokumentenbeschreibungssprache URL als eindeutige Adresse, verwendet in Hyperlinks Spätere Standards CSS als Beschreibungssprache für das Aussehen von Dokumenten JavaScript als Skriptsprache für aktive Seitenelemente HTTPS für Verschlüsselung des Datentransfers Programmierkurs 2 HyperText Markup Language (HTML) HTML ist eine Auszeichnungssprache, mit der Text um Metainformationen angereicht werden kann <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> <html> <head> <title>Titel der Webseite</title> </head> <body> Inhalt der Webseite <a href=„http://www.example.org“>Link</a> </body> </html> HTML-Tags typisieren Metainformationen: <head>, <body>, <a>, <p> HTML-Dokument hat Baumstruktur (Verschachtelung) Programmierkurs 3 Informatik 1/Programmierung Reguläre Ausdrücke (RegExp) Problem: Aus dem HTML-Dokument sollen die URLs & Emailadressen extrahiert werden. Lösung: Parsen durch reguläre Ausdrücke (RegExp) RegExp: Zeichenkette zur Beschreibung von Mengen von Zeichenketten mit Hilfe syntaktischer Regeln. Können als Filterkriterium für Texte dienen Spezielle Zeichenketten in einer Zeichenkette finden („Nadeln im Heuhaufen“). Beispiel Beschreibung einer Postleitzahl: [0-9]{5} Metazeichen dienen der Formulierung von RegExp . = steht für ein (fast) beliebiges Zeichen ^ = Negierung / Komplement Weitere: [ ] ( ) { } | ? + ^ $ \ . Programmierkurs 4 Informatik 1/Programmierung Zeichenklassen Wichtige Konzepte: Zeichenklasse, Quantor, Gruppe Zeichenauswahl / Zeichenklasse: Zeichenklasse in eckiger Klammerung definiert eine Auswahl aus einer Zeichenmenge. Beispiele: [abc] genau einer der Buchstaben a, b oder c [a-z] genau ein Minuskel [0-9] genau eine der Ziffern 0 bis 9 [a-zA-Z0-9] genau ein alphanumerisches Zeichen [^a] genau ein beliebiges Zeichen außer a Negierung Programmierkurs 5 Informatik 1/Programmierung Quantoren Quantoren Drücken Vielfachheit eines vorherigen Ausdrucks aus ? bzw. {0,1} vorheriger Ausdruck ist optional + bzw {1,} voranstehender Ausdruck mindestens einmal * bzw {0,} voranstehender Ausdruck beliebig oft Beispiele: a+ vertritt a, aa, aaa, …. [0-9]+ vertritt Ziffernkombinationen: 1234, 12, 019, 168468465, … [a0-9]{2,5} vertritt 0a129, aa, … aber nicht 123456 [a\[b]+ vertritt z. B. abba[ba, das Zeichen [ ist dabei kein Metazeichen, sondern normales Zeichen wegen Escaping durch \ Vorsicht: In Java muss zweimal escaped werden \\[, da \ auch für Escaping in Java-Strings zuständig ist! Programmierkurs 6 Informatik 1/Programmierung Quantoren: Greedy RegExp kann auf String (Heuhaufen) angewendet werden, und liefert alle Treffer (Nadeln) zurück. Beispiel: [abc]+ auf xxabcbn angewendet gibt abcb zurück Problem: Quantoren sind standardmäßig gierig (greedy) suchen Treffer (Match) mit maximaler Länge, also z. B. abcb Lösung: Durch ? hinter Quantor kann der Quantor als nicht-gierig (non-greedy) definiert werden Beispiel: [abc]+? auf xxabcbn angewendet gibt 4 Treffer: a, b, c, b Treffer mit minimaler Länge werden geliefert. Programmierkurs 7 Informatik 1/Programmierung Gruppen Ausdrücke lassen sich in einer Gruppe mit runden Klammern ( und ) zusammenfassen (abc)+ matcht z. B. die Strings abc und abcabc, aber nicht acbbac, im Gegensatz zu [abc]+ Alternativen können durch | ausgedrückt werden (@|at) matcht entweder @ oder at Weiterführende Adressen: Beschreibung: http://de.wikipedia.org/wiki/Regexp Beispiele: http://regexlib.com/ Tester: http://regexpal.com/ Programmierkurs 8 Informatik 1/Programmierung Beispiele Beispiele: Postleitzahl: [0-9]{5} Vor- und Nachname: [a-zA-ZäöüÄÖÜ]+ [a-zA-ZäöüÄÖÜ]+ Straße und Hausnummer: [a-zA-ZäöüÄÖÜ \.]+ [0-9]+[a-zA-Z]? Uhrzeit: ([0-1][0-9]|[2][0-3]):([0-5][0-9]) Exkurs: Beispiel HTML-Link Wo ist bei diesem RegExp das Problem?: <a href=".*".*> Der Punkt repräsentiert auch die Klammer > und ist gierig. Problem, wenn diese RegExp auf folgenden Text angewendet wird: Text <a href=„http://www.example.org“>Link</a> Text <i>Text</i> Text Lösung: Punkte nicht-gierig machen: <a href=".*?".*?> Programmierkurs 9 Entwicklungsfolie für die Tafel Informatik 1/Programmierung Beispiele Geek-Kultur: 2 b or not b 2 -> „To be, or not to be, …“ (Hamlet, Shakespeare) Programmierkurs 10 Entwicklungsfolie für die Tafel Informatik 1/Programmierung Beispiele Reguläre Ausdrücke für den Parser: Emailadresse: ([a-zA-Z0-9\.\_\-]+)@([a-zA-Z0-9\.\-]+\.[A-Za-z]{2,}) Bei Interesse noch pseudosichere versteckte Emailadressen wie [ät] oder [at] statt @ parsen. Einfache URL ohne HTTP-Authentifizierung oder HTTPS: http:\/\/[a-zA-Z0-9\.\-]+\.[A-Za-z]{2,} Unter http://regexpal.com/ testen. Programmierkurs 11 Entwicklungsfolie für die Tafel RegExp mit Java Java stellt Engine für reguläre Ausdrücke bereit java.util.regex.Pattern speichert regulären Ausdruck in einer kompilierten, effizienten Form. Liefert Matcher. Matcher nimmt String als Input, parst diesen mit Pattern. Matcher.find() sucht nächstes Vorkommen des Pattern im Input Matcher.group() gibt jeweils ein Vorkommen aus. import java.util.regex.*; Pattern pattern = Pattern.compile("[abc]*"); Matcher matcher = pattern.matcher("abcbn"); while (matcher.find()) System.out.println(matcher.group()); -> abcb Programmierkurs 12 Einstiegshilfe public class Parser implements IParser{ private static Parser instance; private Parser(){}; public static Parser getInstance(){ if(instance == null) instance = new Parser(); return instance; } public ArrayList<String> parseEmailAddresses(String content) { //pattern for emailaddresses //build matcher //find matches //save match //return emailaddresses } … } Programmierkurs 13 Weitere Aufgaben Bei Interesse die Klassen Database, Downloader und Parser durch eine Main-Methode steuern und korrekten Ablauf der Methoden testen. Bei Problemen mit dem Ablauf den Debugger von Eclipse benutzen. Verfeinert wird dies im nächsten Kapitel. Programmierkurs 14