Τα δεδομένα του OpenStreetMap (OSM) αποτελούν έναν «θησαυρό» σε κοινή θέα για κάθε δημοσιογραφική χαρτογράφηση. Εδώ, παρουσιάζουμε πώς κανείς μπορεί να ανακτήσει και να επεξεργαστεί στοιχεία του OpenStreetMap, με τη χρήση Python ή QGIS.
Η χαρτογράφηση μπορεί να προσφέρει σημαντικά πλεονεκτήματα σε μια δημοσιογραφική δημοσίευση. Δύναται να απεικονίσει ένα ζήτημα με πιο «σφαιρικό» τρόπο, να αποτελέσει έναυσμα για περαιτέρω διερεύνηση ή ακόμα και μεμονωμένο δημοσιογραφικό περιεχόμενο, με έναν χάρτη χρηστικό για το κοινό. Σε ένα τέτοιο εγχείρημα, τα δεδομένα του OpenStreetMap (OSM) αποτελούν έναν «θησαυρό» σε κοινή θέα. Πρόκειται για ένα συνεργατικό πρότζεκτ χαρτογράφησης που προσφέρει ελεύθερα τα στοιχεία σε όλους (υπό Άδεια Ανοιχτής Βάσης Δεδομένων), και στο οποίο όλοι μπορούν να συνεισφέρουν.
Τα δεδομένα αυτά παρουσιάζονται, όμως, με τον ίδιο τρόπο όπως σε άλλους αντίστοιχους χάρτες. Οπότε, το «κλειδί» για την ανάλυσή τους είναι να τα προσεγγίσουμε μέσω ειδικού λογισμικού ή με προγραμματιστικό τρόπο. Παρακάτω, παρουσιάζουμε δύο προσεγγίσεις που χρησιμοποιήσαμε, μαζί με παραδείγματα, για να χαρτογραφήσουμε στοιχεία σε πόλεις και χώρες ανά τον κόσμο.

Τα δεδομένα
Προτού προχωρήσουμε στην παρουσίαση των παραδειγμάτων, οφείλουμε να αναλύσουμε τη μορφή των δεδομένων, όπως αυτή είναι οργανωμένη εντός του OpenStreetMap (OSM). Το βασικότερο συστατικό στοιχείο του εννοιολογικού μοντέλου δεδομένων που εφαρμόζει το OSM είναι τα «στοιχεία», κάτι σαν τα «τουβλάκια» που χτίζουν τον κόσμο. Υπάρχουν τρία είδη στοιχείων:
- Οι κόμβοι (nodes) που ορίζουν σημεία (points): ένα εστιατόριο, ένα ιατρείο, ένα παγκάκι κλπ.
- Οι γραμμές (ways) που μπορούν είτε να ορίζουν ένα γραμμικό χαρακτηριστικό (π.χ. μία σιδηροδρομική γραμμή) είτε να περικλείουν τα όρια μιας περιοχής, δημιουργώντας ένα πολύγωνο (για παράδειγμα, τα σύνορα μιας χώρας, τα όρια ενός αεροδρομίου και των εγκαταστάσεών του).
- Οι σχέσεις (relations), οι οποίες ορίζουν τη διάδραση μεταξύ άλλων στοιχείων (π.χ. ένα δρομολόγιο λεωφορείου και η λεωφόρος από την οποία περνά)
Στη δική μας ανάλυση, αναζητήσαμε μόνο κόμβους και γραμμές, για να εντοπίσουμε συγκεκριμένα χαρακτηριστικά εντός των περιοχών ενδιαφέροντος. Συγκεκριμένα, ως ενδεικτικό παράδειγμα, παρακάτω θα ανακτήσουμε στοιχεία, με δύο διαφορετικούς τρόπους, για χώρους στάθμευσης στο Κάνσας.
Ο έλεγχος στοιχείων στο OpenStreetMap
Προτού προχωρήσουμε στην ανάκτηση στοιχείων, έχει νόημα να τα ελέγξουμε, μέσω φυλλομετρητή (browser) στο OSM. Για παράδειγμα, έστω ότι ενδιαφερόμαστε για στοιχεία της Αθήνας:
- Ανοίγουμε το OSM στον browser και, στη γραμμή αναζήτησης, πληκτρολογούμε «Αθήνα». Ο χάρτης εστιάζει στην πρωτεύουσα της Ελλάδας, και μια πινέζα εμφανίζεται στο κέντρο της.
- Κάνουμε ζουμ και δεξί «κλικ» στο κέντρο της πόλης και επιλέγουμε «Query Features» («Πληροφορίες Στοιχείων»). Tότε, ανοίγει αριστερό πλευρικό μενού: εκεί, στα «Enclosing Features» («στοιχεία που περικλείουν» μπορούμε να δούμε ότι περιλαμβάνεται το «Administrative Boundary (Level 7) Municipality of Athens». Επιλέγοντας αυτό, βλέπουμε όλο το στοιχείο του διοικητικού ορίου του Δήμου Αθηναίων, και κάτω από τα «Tags» (Ετικέτες) το αγγλικό όνομα της πόλης, όπως είναι στο σύστημα: «Municipality of Athens».

Αντίστοιχα, για να εντοπίσουμε τον σωστό όρο των στοιχείων που θέλουμε να αναζητήσουμε, συμβουλευόμαστε τα «Tags» («Ετικέτες»). Αυτά αποτελούνται από δύο συνθετικά, ένα πρωτεύον (π.χ. «amenity») και ένα δευτερεύον (π.χ. «parking»). Όπως και με το όνομα της Αθήνας, έτσι και στην εκάστοτε κατηγορία, για τα στοιχεία που επιθυμούμε να χαρτογραφήσουμε, πρέπει να εντοπίσουμε τη σωστή ορολογία με την ίδια διαδικασία.

Προσέγγιση 1: Ανάκτηση δεδομένων με Python
Στην πρώτη –και ομολογουμένως πιο περίπλοκη– μέθοδο χρησιμοποιούμε πρόγραμμα, σε γλώσσα προγραμματισμού Python, για να κατεβάσουμε το σύνολο των στοιχείων για την περιοχή ενδιαφέροντος και εντοπίζουμε, στο σύνολο των στοιχείων αυτών, εκείνα που είναι σχετικά με την ανάλυση.
Στο πρώτο βήμα, ορίζουμε την περιοχή ενδιαφέροντος. Πρέπει να οριστεί στα αγγλικά και με πανομοιότυπο τρόπο με αυτόν που εμφανίζεται μέσα στους χάρτες του OSM – π.χ. «Municipality of Athens». Στην προκειμένη περίπτωση, χρησιμοποιήσαμε τη Γουίτσιτα του Κάνσας ως το παράδειγμα.
Τα δεδομένα «κατεβαίνουν», χρησιμοποιώντας τη βιβλιοθήκη quackosm από server της Geofabrik, μίας γερμανικής εταιρείας που διαθέτει δωρεάν καθημερινές εξαγωγές δεδομένων από το OpenStreetMap.
Στο επόμενο βήμα, ο κώδικας λαμβάνει τα στοιχεία που έχουν τις παραμέτρους που επιλέξαμε (στο δικό μας παράδειγμα τα «amenity» + «parking») εντός της περιοχής ενδιαφέροντος, και τα συγκεντρώνει σε ένα dataframe με γεωγραφικές συντεταγμένες.
Ολόκληρος ο κώδικας για την συγκέντρωση και χαρτογράφηση των χώρων στάθμευσης στη Γουίτσιτα του Κάνσας
!pip install quackosm folium geopandas -q
import quackosm as qosm
import geopandas as gpd
from shapely.ops import unary_union
import folium
from IPython.display import display
import pandas as pd
import colorsys
# ─── CHANGE ONLY THIS BLOCK ───────────────────────────────────────────────────
PLACES = [
"Wichita",
]
TAGS = {
"amenity": ["parking" ]
}
DISPLAY_COLS = ["name", "amenity"]
# ──────────────────────────────────────────────────────────────────────────────
geometries = [qosm.geocode_to_geometry(p) for p in PLACES]
geometry_filter = unary_union(geometries)
gdf = qosm.convert_geometry_to_geodataframe(
geometry_filter=geometry_filter,
tags_filter=TAGS,
osm_extract_source="Geofabrik",
keep_all_tags=True,
explode_tags=False,
verbosity_mode="transient",
)
gdf["name"] = gdf["tags"].apply(lambda t: t.get("name") if isinstance(t, dict) else None)
gdf["amenity"] = gdf["tags"].apply(lambda t: t.get("amenity") if isinstance(t, dict) else None)
cols_to_show = [c for c in DISPLAY_COLS if c in gdf.columns]
if gdf.empty:
print("No features found.")
else:
TAG_COLS = [c for c in gdf.columns if c not in ("geometry", "tags", "name")]
def get_feature_label(row):
tags = row.get("tags")
if not isinstance(tags, dict):
return "other"
for key in TAGS:
val = tags.get(key)
if val and pd.notna(val):
return f"{key}: {val}"
for key, val in tags.items():
if val and pd.notna(val):
return f"{key}: {val}"
return "other"
gdf["_label"] = gdf.apply(get_feature_label, axis=1)
unique_labels = sorted(gdf["_label"].unique())
def make_palette(n):
palette = {}
for i, label in enumerate(unique_labels):
if label == "other":
palette[label] = "#72D61A"
else:
hue = i / max(n, 1)
r, g, b = colorsys.hsv_to_rgb(hue, 0.75, 0.88)
palette[label] = "#{:02x}{:02x}{:02x}".format(
int(r * 255), int(g * 255), int(b * 255)
)
return palette
palette = make_palette(len(unique_labels))
bounds = gdf.total_bounds
center_lat = (bounds[1] + bounds[3]) / 2
center_lon = (bounds[0] + bounds[2]) / 2
m = folium.Map(
location=[center_lat, center_lon],
zoom_start=12,
tiles="CartoDB positron"
)
folium.TileLayer("OpenStreetMap", name="OpenStreetMap").add_to(m)
for _, row in gdf.iterrows():
name = row.get("name") or "Unnamed"
geom = row.geometry
point = geom if geom.geom_type == "Point" else geom.centroid
label = row["_label"]
color = palette[label]
tags = row.get("tags") or {}
popup_fields = [f"<b>{name}</b>"] + [
f"{k}: {v}" for k, v in tags.items() if v and pd.notna(v)
]
popup_html = "<br>".join(popup_fields)
folium.CircleMarker(
location=[point.y, point.x],
radius=6,
color=color,
fill=True,
fill_color=color,
fill_opacity=0.85,
tooltip=f"{name} ({label})",
popup=folium.Popup(popup_html, max_width=280),
).add_to(m)
legend_items = "".join(
f'<div style="display:flex;align-items:center;margin-bottom:5px">'
f'<div style="width:14px;height:14px;border-radius:50%;background:{color};'
f'margin-right:8px;flex-shrink:0"></div>'
f'<span style="font-size:12px">{label}</span></div>'
for label, color in sorted(palette.items())
)
legend_html = f"""
<div style="
position: fixed; bottom: 40px; left: 40px; z-index: 1000;
background: white; padding: 12px 16px; border-radius: 8px;
box-shadow: 0 2px 8px rgba(0,0,0,0.2); max-height: 320px;
overflow-y: auto; font-family: sans-serif;
">
<div style="font-weight:bold;margin-bottom:8px;font-size:13px">Feature types</div>
{legend_items}
</div>
"""
m.get_root().html.add_child(folium.Element(legend_html))
folium.LayerControl().add_to(m)
m.fit_bounds([[bounds[1], bounds[0]], [bounds[3], bounds[2]]])
display(m)

Ένα σύνολο δεδομένων σε dataframe είναι πάντα χρήσιμο, αλλά ακόμα πιο εύχρηστο αν οπτικοποιηθεί σε χάρτη, και ειδικά διαδραστικό. Οπότε, στο τελευταίο βήμα του κώδικά μας, χρησιμοποιούμε τη βιβλιοθήκη folium, για να χαρτογραφήσουμε τα στοιχεία που συγκεντρώσαμε.
Δημιουργούμε δυναμικά μια παλέτα χρωμάτων, για να διαφοροποιηθούν οπτικά τα διαφορετικά στοιχεία που μπορεί να έχουμε συγκεντρώσει. Η διαφοροποίηση γίνεται επί του δευτερεύοντος χαρακτηριστικού. Οπότε, για παράδειγμα, εάν υπάρχουν περισσότερα από δύο «amenities» («parking», «place of worship»), τότε θα λάβουν από ένα ξεχωριστό χρώμα. Επίσης, για να είναι πιο ομοιογενής η οπτικοποίηση των στοιχείων, αλλάζουμε τα πολύγωνα σε σημεία, εντοπίζοντας το κεντροειδές τους, δηλαδή το κεντρικό τους σημείο.
Αυτή η προσέγγιση είναι πιο περίπλοκη, με δεδομένο ότι απαιτεί και βασικές γνώσεις Python, αλλά μπορεί να φανεί χρήσιμη, εάν κανείς δεν θέλει να «φορτώσει» τον υπολογιστή του με πρόσθετα λογισμικά. Άλλωστε, και ο ίδιος κώδικας μπορεί να τρέξει στο cloud, χρησιμοποιώντας Google Colab Notebook.

Προσέγγιση 2: QGIS και ένα μικρό plug-in
Η πιο εύκολη μέθοδος για τον εντοπισμό των στοιχείων χωρίς να μπαίνουμε σε διαδικασίες ανάπτυξης κώδικα είναι η αξιοποίηση του δωρεάν, ανοιχτού λογισμικού γεωχωρικής ανάλυσης QGIS, με το οποίο μπορεί κανείς να δημιουργήσει και να επεξεργαστεί στοιχεία χαρτογραφικών δεδομένων.
Για την εγκατάσταση και έναν ευρύτερο οδηγό για το πώς θα χρησιμοποιήσετε το QGIS μπείτε εδώ.
Για να κατεβάσετε τα δεδομένα από το OSM στο πρότζεκτ σας εντός του QGIS, πρέπει να έχετε κατεβάσει το plug-in «QuickOSM». Για να το κάνετε αυτό, απλώς πηγαίνετε στις επιλογές στο πάνω αριστερά μέρος της οθόνης σας. εντός του QGIS, επιλέξτε το «Plugins» και έπειτα το «Manage and Install Plugins». Τότε, αναζητήστε το «QuickOSM» και εγκαταστήστε το στο QGIS. Όταν θα το έχετε εγκαταστήσει επιτυχώς, θα έχετε το πράσινιο εικονίδιο της αναζήτησης, πάνω από το τμήμα των «Layers».
Απαραίτητο βήμα για να δουλέψετε με τα συγκεκριμένα δεδομένα είναι να ανοίξετε αρχικά μία επίστρωση χάρτη από το OSM εντός του QGIS, ώστε να έχετε εικόνα των στοιχείων. Για να το κάνετε αυτό πρέπει να ακολουθήσετε την εξής διαδρομή: Layer > Add layer > Add XYZ layer.

Στο τελευταίο βήμα, από το μενού «Custom», διαλέγετε το OpenStreetMap και πατάτε το «Αdd», στο κάτω δεξιά μέρος του παραθύρου.

Ανοίγοντας, λοιπόν, το QuickOSM (πράσινο εικονίδιο αναζήτησης), θα βρεθείτε μπροστά σε μια λίστα προεπιλεγμένων queries που μπορείτε να κάνετε. Για να συγκεντρώσετε, όμως, τη λίστα των αντικειμένων που εσείς επιθυμείτε, για την περιοχή που επιθυμείτε, πατήστε το «Quick query» (από τα αριστερά).

Εκεί, θα χρειαστεί να συμπληρώσετε τα στοιχεία που θέλετε να βρείτε με την ίδια λογική που ακολουθήσαμε στην προσέγγιση με την Python. Έτσι, εν προκειμένω, για να εντοπίσουμε όλους τους χώρους στάθμευσης στην πόλη της Γουίτσιτα στο Κάνσας, θα γράψουμε στο key «amenity» και στο value «parking». Έπειτα, υπάρχει το μενού της περιοχής. Εδώ προσφέρονται διαφορετικές επιλογές:

- «In»: εντοπίζουμε όλα τα στοιχεία που βρίσκονται εντός ενός γεωγραφικού χώρου –στην προκείμενη περίπτωση, εντός των διοικητικών ορίων της πόλης της Γουίτσιτα, που έχουμε δει ότι στο OSM είναι καταχωρημένη με την ίδια ονομασία.
- «Around»: βρίσκονται τα στοιχεία που είναι εντός μιας ορισμένης ακτίνας από ένα γεωγραφικό στοιχείο.
- «Canvas extent»: με αυτήν την επιλογή, δεν αναγράφουμε κάποια συγκεκριμένη περιοχή για να εντοπιστούν στοιχεία, καθώς κατεβαίνουν όλα όσα φαίνονται στον χάρτη εντός του περιβάλλοντος του QGIS.
- «Layer extent»: με αυτήν την προσέγγιση, κατεβαίνουν όλα τα στοιχεία που βρίσκονται εντός των γεωγραφικών ορίων μιας ήδη υπάρχουσας επίστρωσης. Για παράδειγμα, έχετε μία επίστρωση σε μορφή πολυγώνου που έχει τα όρια μιας περιοχής Natura. Με αυτήν την επιλογή, θα βρείτε όλα τα στοιχεία εντός της.
- «Non spatial»: κατεβαίνουν όλα τα επιλεγμένα στοιχεία χωρίς προσδιορισμό γεωγραφικού ορίου.
Ακολουθώντας αυτά τα βήματα έχουμε συγκεντρώσει, λοιπόν, όλους τους χώρους στάθμευσης εντός των διοικητικών ορίων της πόλης Γουίτσιτα στο Κάνσας των ΗΠΑ, όπως αναφέρονται στο OSM.

Εάν θέλουμε να κάνουμε και ένα περαιτέρω βήμα για μια ομοιογενή οπτικοποίηση των στοιχείων, εντοπίζουμε τα κεντροειδή (centroid) τους, ώστε και τα πολύγωνα και οι γραμμές να έχουν την ίδια μορφή εντός του χάρτη. Για να υπολογιστεί αυτό, η διαδικασία είναι: Vector > Geometry Tools > Centroids. Τότε, διαλέγουμε την επίστρωση που επιθυμούμε να επιλέξουμε και πατάμε το «Run». Έτσι, τα στοχεία θα εμφανίζονται σε όλα τα επίπεδα ζουμ που εφαρμόζουμε στον χάρτη.
