885549_industrial_past

The Groovy Way: Daten aus HTML extrahieren

Hier ist der “Groovy Way” um aus einer HTML-Datei Daten zu extrahieren. Als Beispiel sollen alle deutschen Großstädte mit der Einwohnerzahl ausgegeben werden (Wikipedia).

Als Parser bietet Groovy den eingebauten XmlSlurper an. Dieser funktioniert sehr gut bei XML, aber bei HTML ergeben sich Probleme, z.B. beim Fehlen von schließenden Tags. Lösung ist die Verwendung eines alternativen SAXParsers, der mit HTML richtig umgehen kann (TagSoup). Die Einbindung von TagSoup erfolgt mit @Grab in der Zeile 1, damit erspart man sich das Herunterladen der Bibliothek. Und in der Zeile 3 wird der alternative SaxParser gesetzt.

Die Zeilen 4 und 5 lesen und parsen die HTML-Datei. Das Lesen der Datei ist hier wegen eines UTF8-Errors etwas umständlich.

Jetzt extrahieren wir die gewünschten Daten (Stadt und Einwohnerzahl). Dazu suchen wir in der Zeile 7 die entsprechende Tabelle, iterieren anschließend über alle Zeilen und holen die Werte aus der zweiten und sechsten Spalte (Zeilen 11 und 12).

@Grab(group='org.ccil.cowan.tagsoup', module='tagsoup', version='1.2' )

def slurper = new XmlSlurper(new org.ccil.cowan.tagsoup.Parser())
Reader streamReader = new InputStreamReader( new FileInputStream("index.htm"), "UTF-8")
def htmlParser = slurper.parse(streamReader) // parse nimmt auch eine URL

def table = htmlParser.'**'.find{ it.name() == 'table' && it.@class == 'wikitable sortable'}
table.tr.eachWithIndex { row, rowIdx ->
	def city, people
	row.'**'.findAll { it.name() == 'td' }.eachWithIndex { value, index ->
		if (index == 1) city = value.a.text()
		if (index == 5) people = Float.valueOf(value.span.text()) as Integer
	}
	if (city) println "$city -> $people"
}

Als Ergebnis erhalten wir:

...
Reutlingen -> 112484
Remscheid -> 110563
Koblenz -> 106417
Bergisch Gladbach -> 105723
Erlangen -> 105629
Moers -> 105506
Trier -> 105260
Jena -> 105129
Siegen -> 103424
Hildesheim -> 102794
Salzgitter -> 102394
Cottbus -> 102091