Was geht denn hier ab?

Polizeiberichte in interaktiven Online-Karten darstellen

Wo um mich herum wird eingebrochen, wo passieren Unfälle? Während es in Nordamerika üblich ist, die Antwort darauf zeitnah im Web aus interaktiven Online-Karten zu bekommen (z.B. in Toronto), muss man in Deutschland die Berichte der Polizei aufmerksam lesen, um sich ein Bild davon zu machen.

Oder kann das nicht der Computer für mich übernehmen?

Die geographische Datenwissenschaft kann uns tatsächlich weiterhelfen. Was müssen wir tun, um Polizeiberichte auf eine Karte zu bekommen?

  1. Web-Scraping: Die von der Thüringer Polizei veröffentlichten Berichte einlesen und enthaltene Informationen extrahieren.
  2. Geoparsing: Straßennamen erkennen und herausfiltern.
  3. Geocodierung: Die Straßennamen in Koordinaten umwandeln.
  4. Web-Mapping: Ein interaktives Kartendisplay fürs Web erzeugen.

Klingt kompliziert? Wer im Geoinformatik-Studium bei uns in Jena aufgepasst hat, wird keine Schwierigkeiten damit haben… ;-) Hier eine schnelle und einfache Lösung, die noch nicht das Letzte aus den Daten herausholt, aber für einen Samstagnachmittag doch recht ordentlich ist.

Ich verwende hierfür die freie Statistik-Software R mit den Packages rvest und leaflet sowie offene Thüringer Geodaten der ALKIS-Datenbank. (In vielen anderen Bundesländern sind diese Daten leider nicht frei zugänglich, aber es ließen sich auch andere offene Quellen anzapfen.)

Web-Scraping: Informationen aus dem Web ernten

Nicht nur Menschen, sondern auch Computerprogramme – sogenannte Bots – können Webseiten lesen und die Inhalte verarbeiten. Das ist unter bestimmten Voraussetzungen völlig legal und wird tagtäglich für alle möglichen Zwecke eingesetzt, aber ich empfehle, stets vorher die rechtlichen Rahmenbedingungen zu prüfen und rücksichtsvoll von den technischen Möglichkeiten Gebrauch zu machen.

Die Thüringer Polizei stellt ihre Berichte direkt in presseportal.de ein, wo sie auf Seiten wie dieser übersichtsartig dargestellt sind:

Die Inhalte und Formatierungen der Webseiten liegen dabei im HTML-Format vor – hier ein kleiner Ausschnitt:

Das lässt sich wiederum mit rvest-Funktionen in R analysieren. In einfachster Form sieht das so aus, wobei uns sehr gelegen kommt, dass die Polizeiberichte selbst einfach in Links der Form /blaulicht/pm/ eingebettet sind.

suppressMessages(library(tidyverse))
suppressMessages(library(rvest))
# Webseite lesen:
html <- read_html(url("https://www.presseportal.de/blaulicht/r/Jena"))

# HTML-Abschnitte mit Polizeiberichten filtern:
x <- html %>% html_nodes("ul")
sel <- str_starts(html_attr(x, "class"), "article-list row")
sel[is.na(sel)] <- FALSE
x <- x[sel] %>% html_nodes("article")

# URLs extrahieren:
urls <- x %>% map_chr(function(y) html_attr(html_nodes(y, "a")[2], "href"))
sel <- str_detect(urls, "/blaulicht/pm/")
urls <- urls[sel]

# Nur die 'article'-Abschnitte mit Polizeiberichten:
x <- x[sel]

# Inhalte:
titles <- x %>% map_chr(function(y) html_text(html_nodes(y, "a")[2]))
reports <- x %>% map_chr(function(y) html_text(html_nodes(y, "p")[2]))
towns <- reports %>% str_extract("^.* \\(ots\\)") %>%
  str_remove(" \\(ots\\)")
dates <- x %>% html_node("div .date") %>% html_text()

# Ergebnisse sammeln:
d <- data.frame(
  url = urls,
  title = titles,
  town = towns,
  text = reports,
  date = dates
)

# Nur Polizeiberichte aus Jena:
sel <- !is.na(d$town) & str_starts(d$town, "Jena")
d <- d[sel,]

Damit haben wir schon eine Tabelle mit den Meldungen (Titel und Text), ihrem Ort (nur Jena), und jeweils einer weiterführenden URL. Insgesamt sind es 28 Berichte, hier nur die ersten drei (ohne die ausführlichen Berichtstexte selbst):

d[1:3, 1:3]
##                                                       url
## 1 https://www.presseportal.de/blaulicht/pm/126722/5183597
## 2 https://www.presseportal.de/blaulicht/pm/126722/5183596
## 3 https://www.presseportal.de/blaulicht/pm/126722/5183595
##                                        title town
## 1             LPI-J: Schmierfinken unterwegs Jena
## 2 LPI-J: Baustelle als Selbstbedienungsladen Jena
## 3        LPI-J: Technik aus Schule entwendet Jena

Geoparsing: Toponyme in Texten entdecken

Die Berichte enthalten zwar keine genauen Koordinaten der Vorfälle, wohl aber in den meisten Fällen Straßennamen, also spezielle Toponyme. Das Auffinden von Toponymen in Texten, also das sogenannte Geoparsing, kann eine ganz schöne Herausforderung sein, weil es wahnsinnig viele Toponyme gibt und diese auch noch “normalen” Wörtern ähneln können – erst kürzlich betreute ich mit Dr. Xuke Hu vom DLR-institut Jena die Abschlussarbeit von Tim Grünemay zum Geoparsen von Social-Media-Nachrichten, wo es dickere Bretter zu bohren gab.

Zum Glück haben wir es hier etwas leichter als Tim: Die Polizeiberichte sind (meist) sehr präzise in den Ortsbezeichnungen, Rechtschreibfehler sind eine Rarität, und in Jena gibt es nur eine begrenzte Anzahl Straßennamen – genau genommen 869 Stück. (Dafür fehlen uns Hausnummern, so dass die Lagegenauigkeit leider nicht optimal sein wird.)

Aus ALKIS-Daten, die eigentlich auf sogar Gebäudeebene vorliegen, habe ich daher zunächst einen Straßendatensatz erzeugt (hier verfügbar)…

streets <- readRDS("Jena_streets.rds")

… der so aussieht:

STN lat lon
Adlerstieg 50.93248 11.61699
Adolf-Reichwein-Straße 50.90785 11.57352
Adrian-Beier-Stieg 50.92924 11.60207
Ahornstraße 50.90532 11.57950
Ahornweg 50.96244 11.52533

Mit einfachen Textvergleichen können wir nun die im Polizeibericht vorkommenden Jenaer Straßennamen auffinden; nur für den Markt habe ich mir eine Sonderregel ausgedacht, um nicht auf jeden Supermarkt im Text hereinzufallen:

# Geoparsing-Funktion:
geoparse <- function(x, streets) {
  sel <- sapply(streets$STN, function(y) any(grepl(y, x, ignore.case = TRUE)))
  sel <- streets$STN[sel]
  if ((length(sel) > 1) & any(sel == "Markt"))
    sel <- sel[ sel != "Markt" ] # "Markt" weg, wenn auch Straße angegeben
  sel
}
# Probier's aus:
geoparse(d$text[1], streets = streets) # ohne Jenaer Straßennamen
## [1] "Emil-Wölk-Straße" "Zwätzengasse"
geoparse(d$text[2], streets = streets)
## [1] "Erfurter Straße"

Jetzt müssen wir nur noch die Koordinaten der Straßen finden und diese auf die Karte bringen!

Geocodierung: Toponyme in Koordinaten umwandeln

Da der ALKIS-Datensatz (bzw. mein abgeleiteter Straßendatensatz) auch Koordinaten enthält, können wir diese nun anhand der Straßennamen nachschlagen – das ist die Geocodierung, eine essentielle Operation in vielen Geoinformatik-Anwendungen vom Geomarketing bis zur Routenfindung.

Wenn mehr als ein Straßenname vorliegt, nehme ich die mittlere Koordinate. (Den Kreuzungspunkt zu finden wäre Fleißarbeit, die ich dir überlasse!) So sieht das aus:

# Funktion zum Geocodieren von Straßennamen:
geocode <- function(x, streets) {
  sel <- streets$STN %in% x
  data.frame( # Median, falls es mehrere sind:
    lat = median(streets$lat[sel]),
    lon = median(streets$lon[sel]),
    streets = paste(x, collapse = ", ")
  )
}
# Probier's aus:
geocode("Stadtrodaer Straße", streets = streets)
##        lat      lon            streets
## 1 50.87704 11.62894 Stadtrodaer Straße
geocode(c("Löbdergraben", "Sonnenhof"), streets = streets)
##        lat      lon                 streets
## 1 50.92724 11.58875 Löbdergraben, Sonnenhof

Damit sind wir bereit, das Geoparsing und die Geocodierung nacheinander auf alle Texte loszulassen:

xy <- d$text %>% map(geoparse, streets = streets) %>% 
  map(geocode, streets = streets) %>% bind_rows()
d <- cbind(d, xy)
d <- d[!is.na(d$lat), ] # nur Berichte mit Koordinaten

Von den 28 gefundenen Berichten konnten wir immerhin 22 Exemplare geocodieren. Es gibt auch zahlreiche Geocodierdienste im Internet, aber es ist schon sehr praktisch, dass wir in Thüringen direkt auf freie ALKIS-Daten zugreifen können!

Web-Mapping: interaktive Karten im Web erstellen

Jetzt auf die Karte damit! Die Darstellung übernimmt für uns ein Package namens leaflet, welches wiederum offene Geodaten z.B. von OpenStreetMap im Hintergrund einblendet.

library(leaflet)
d$popup <- paste0('<a href="https://www.presseportal.de', d$url, '">', 
                  '<strong>', d$title, '</strong></a><p>',
                  d$date, "<br>",
                  d$streets, '<p>"', d$text, '"<p>', 
                  'Quelle: Polizei via presseportal.de')
leaflet() %>% addTiles() %>%
  addCircleMarkers(lat = d$lat, lng = d$lon, popup = d$popup, radius = 5)

Ich habe die obige Analyse noch ein bisschen ausgedehnt und verfeinert und damit etwa ein Jahr an Polizeiberichten geocodiert. Das Ergebnis sieht so aus:

Die Lage der Ereignisse stimmt bestenfalls(!) auf Straßenebene und kann in Einzelfall ganz falsch sein! Ich gebe keine Gewähr für die Richtigkeit der Informationen! Maßgeblich sind die vollständigen Original-Berichte, die jeweils in den Popup-Blasen verlinkt sind.

Bei genauerer Betrachtung fallen uns zwar noch ein paar Fehler auf, mit denen sich vielleicht noch jemand in einer Abschlussarbeit auseinandersetzen möchte! Ich habe das gleich für alle größeren Städte in Thüringen gemacht – unten die Ergebnisse für Erfurt, Weimar und Gera.

Web-Mapping und die Reproduktion von Verzerrungen

War’s das? Gerade die kartographische Darstellung der scheinbar objektiven polizeilichen Informationen verleitet dazu, denn darin erkennbaren räumlichen Mustern blind zu vertrauen. Das ist jedoch nicht unproblematisch:

  • Nicht alle potenziell berichtenswerten Vorfälle werden der Polizei mitgeteilt (Underreporting). Das kann verschiedenste Gründe haben… (Ich könnte da noch einen Fahrradsturz beitragen, denn ich vielleicht hätte melden sollen… siehst du den Punkt, der auf dem Radweg hinter Kunitz nicht zu sehen ist?)
  • Polizeiliche Handlungspraktiken können verstärkt bestimmte Bevölkerungsgruppen oder vermeintliche oder tatsächliche Gefahrengebiete innerhalb von Städten in den Fokus nehmen, was eine weitere Quelle von Verzerrungen darstellt (vgl. dieser Beitrag der Bundeszentrale für politische Bildung).
Die hier dargestellten Punktmuster reproduzieren die in den zugrundeliegenden Daten enthaltenen Verzerrungen.

Wir müssen mit diesen Informationen also kritisch umgehen und uns darüber im Klaren sein, dass die in den Karten erkennbaren Muster nunmal alle Verzerrungen reproduzieren, die in der Entstehung der Daten angelegt sind! Bei der Nutzung dieser Informationen ist dies unbedingt zu berücksichtigen – sei es in der Polizeiarbeit (Geopolicing, Predictive Policing), der sozialgeographischen Sicherheitsforschung, oder wenn wir uns in diesen Karten einfach nur in unserem Wohnumfeld umschauen wollen, was mir jedenfalls für heute ausreichen soll.

Weitere Thüringer Städte

Erfurt

Weimar

Gera

comments powered by Disqus

Related