alle Schulen: als nodes, areas (polygons oder multipolygon) objects?

Hallo Community,

Ein OSM Overpass API Beispile mit PHP SimpleXML;

**update: ** hab die bounding-box nochmals geaendert - so muesste es gehen


<?php
/**
 * OSM Overpass API with PHP SimpleXML / XPath
 *
 * PHP Version: 5.4 - Can be back-ported to 5.3 by using 5.3 Array-Syntax (not PHP 5.4's square brackets)
 */

//
// 1.) Query an OSM Overpass API Endpoint
//


$query = 'node
  ["addr:postcode"~"RM12"]
  (51.5557914,0.2118915,51.5673083,0.2369398);
   node
  (around:1000)
  ["amenity"~"fast_food"];
           out;';
$context = stream_context_create(['http' => [
    'method'  => 'POST',
    'header' => ['Content-Type: application/x-www-form-urlencoded'],
    'content' => 'data=' . urlencode($query),
]]);



Manche Schulen sind als nodes, andere als areas (polygons oder multipolygons), oder beides abgelegt.
Wie kann ich alle Schulen bekommen?

Wenn ich mehr schreiben soll, dann lasst es mich bitte wissen.

Also ich wĂĽrde den ersten (Umkreis) Punkt mit einem alias belegen und anschlieĂźend diesen Alias bei around verwenden und dann halt fĂĽr way nochmal dasselbe:


$query = 'node
  ["addr:postcode"~"RM13"]
  (51.6757914,0.2338915,51.4473083,0.2365598)->.point;
  (
  node
  (around.point:100000)
  ["amenity"~"school"];
  way
  (around.point:100000)
  ["amenity"~"school"];
  );
  out;';

PS: Ăśbrigens bekomme ich einen Fehler wenn ich versuche deine Abfrage auszufĂĽhren, da irgendwas mit der bbox Angabe nicht passt.

1 Like

Um dann aus dem Ergebnis alle drei Typen auszuwählen gibt es mindestens zwei Möglichkeiten:

  • Die Overpass-API kann afaik etwas wie “all-to-nodes”.

  • SimpleXML kann XPath. In diesen Anfragen kann man per Wildcard Elementenebenen im DOM ĂĽberspringen.

1 Like

hallo rayquaza hallo Harald,

vielen Dank für eure Antworten - werde das am WE alles mal näher ansehen.

Habe die Bounding-Box oben mal noch korrigiert. Jetzt muesste was rauskommen.

die moeglichkeiten die ihr aufzeigt sind sehr vielversprechend:

  • all-to-nodes kenn ich auch aus osmconvert / - filter.
  • mit XPath. per Wildcard Elementenebenen im DOM ĂĽberspringen seh ich mir am WE mal an.

es mĂĽsste eine Abfrage sein, welche alle Objektarten erfasst - wie hier beschrieben:

nodes, ways and relations - All kind of objects

cf http://wiki.openstreetmap.org/wiki/Overpass_API/Language_Guide#All_kind_of_objects

And, finally, we search for all kind of objects with a certain tag within a bounding box. You need to repeat the tag for every type and to use the union operator. To allow us displaying everything on a map, we also ask for the nodes and ways that are referred by the relations and ways in the result:
Overpass XML

by the way: Harald - du nimmst dieses “itterative” Moment ja auch in deiner Erklärung auf - und formulierst die Abfrage für ways und node! - siehe oben!


<osm-script>
  <union>
    <query type="node">
      <has-kv k="amenity" v="fire_station"/>
      <bbox-query e="7.3" n="50.8" s="50.6" w="7.0"/>
    </query>
    <query type="way">
      <has-kv k="amenity" modv="" v="fire_station"/>
      <bbox-query e="7.3" n="50.8" s="50.6" w="7.0"/>
    </query>
    <query type="relation">
      <has-kv k="amenity" modv="" v="fire_station"/>
      <bbox-query e="7.3" n="50.8" s="50.6" w="7.0"/>
    </query>
  </union>
  <union>
    <item/>
    <recurse type="down"/>
  </union>
  <print/>
</osm-script>


geht man also von dem obigen Beispiel aus - dann sollte das analo so wie hier unten aussehen - also alles vorhanden sein



$query = 'node
  ["addr:postcode"~"RM12"]
  (51.5557914,0.2118915,51.5673083,0.2369398);
   node
  (around:1000)
  ["amenity"~"fast_food"];
           out;';

$query = 'way
  ["addr:postcode"~"RM12"]
  (51.5557914,0.2118915,51.5673083,0.2369398);
   node
  (around:1000)
  ["amenity"~"fast_food"];
           out;';

               
$query = 'relation'
  ["addr:postcode"~"RM12"]
  (51.5557914,0.2118915,51.5673083,0.2369398);
   node
  (around:1000)
  ["amenity"~"fast_food"];
           out;';

           
 kurz gefasst also die drei query-types:   

         
    <query type="node">
    <query type="way">
    <query type="relation">
           

@ Harald: du hast diesen Sachverhalt in deinem Antwrortschreiben auch schon erwähnt.

was meint ihr denn.

vg tagtheworld

Meld mich wieder.

VG

**update; ** betreffend den Wildcards von Xpath im DOM denke ich dass es hier auch angesprochen ist:

http://stackoverflow.com/questions/4203119/xpath-wildcards-on-node-name

This is the correct XPath 1.0 expression wich select an element with last 5 character of name
equal to

 "_cost" 

in any namespace.

/data/stats/*[substring(name(), string-length(name()) - 4) = '_cost']

With XPath 1.0 you can use

  /data/stats/*[substring-after(name(), '_cost') = ''] 

pattern.

That checks if element’s name ends with the _cost suffix.

In XPath 2.0 there is

  fn:ends-with(str, str) 

and your corresponding experssion will be

 *[ends-with(name(), '_cost')]. 

Und - hats geklappt?

Eine Alternative wäre noch diese hier:

  1. Deutschland-Datei besorgen
    wget http://download.geofabrik.de/europe/germany-latest.osm.pbf

  2. Umwandeln ins Format .o5m (lässt sich von osmfilter schneller verarbeiten als .osm)
    osmconvert germany-latest.osm.pbf -o=germany.o5m

  3. Schulen rausfiltern
    osmfilter germany.o5m --keep=“amenity=school” -o=schulen.o5m

Jetzt hast du eine Datei mit den OSM-Daten aller Schulen. Diese Datei kannst du nun umwandeln in das Format, das du brauchst. Zum Beispiel:

4a) Umwandeln in .osm
osmconvert schulen.o5m -o=schulen.osm
(du hättest bei 3. natürlich auch gleich .osm als Ausgabeformat angeben können)

4b) Umwandeln in .csv
osmconvert schulen.o5m --csv=“name addr:city website” -o=schulen.csv

Die Datei schulen.csv enthält dann ungefähr sowas:

(...)
Grundschule Au		
Berufskolleg JĂĽlich	JĂĽlich	http://www.berufskolleg-juelich.de/
Gymnasium Zitadelle	JĂĽlich	http://www.zitadelle.juel.nw.schule.de/
Alexander-Hegius-Grundschule		
Schule am Wald		
KGS PassstraĂźe	Aachen	
Grundschule FuhsestraĂźe		
1. Gemeinschaftsschule	Berlin	http://www.campusrĂĽtli.de/
Grundschule Leezdorf		
Fritz-Schubert-Schule	Maintal	
St. Ludgerus Kindergarten		
Lauder-Morijah-Grundschule		http://www.sgk.de/index.php/schule.html
Joh.-Kepler-Gymnasium		
Maximilian-Kolbe-Gymnasium	Wegberg	
Edith-Stein-Realschule		
Erich-Kästner-Grundschule		http://www.eks-wegberg.de
(...)

guten Morgen Marqqs,

Vorweg vielen Dank fĂĽr deine Antwort. :slight_smile: Freue mich sehr!!

Das ist ja auch eine Supermethode. Und ich glaube dass ich deine Methode auch verwenden kann mit einer DB-Anbindung - ergo also die DATEN schlussendlich in einer DB speichern kann. Das muesste da auch gut gehen. Aehnlich wie mit dem hier angesprochenenen PHP-Beispiel.
Und ganz ganz wichitig: ich kann bei Deiner von dir beschriebenen Methode auch angeben, dass mir alle DATEN (TAGS) ausgegeben werden. Also alles was zu Schulen gehoert… gell!? Das wäre wichtig. Aber so wie ich osmfilter /.-convert verstanden hab, geht das dort alles prächtig. :wink:

Um auf deine Frage zu kommen: mit dem xpath-query häng ich immer noch etwas. (vgl. auch http://forum.openstreetmap.org/viewtopic.php?id=25905 )

Obwohl das mit dem Abfragen nach den versch. Vorkommnissen (vgl diesen Threadstart) von Schulen klappt -also.

               
$query = 'relation'
$query = 'node'
$query = 'way'


-… das scheint zu gehen.

Aber bei der FRAGE mit dem xpath-query häng ich immer noch etwas. vgl http://forum.openstreetmap.org/viewtopic.php?id=25905 Harald Hartmann hat dort schon sehr gute Ideen genannt - die ich halt umsetzen müsste. Muss mal sehen ob mir das gelingt… Bin noch nicht soo fit in PHP.

Frage: wie muss ich die xpath-requests erweitern dass ich nicht nur die daten erhalte

id
lat
lon
name (und ggf. noch ein default fĂĽr unnamed)

sehr sehr gerne hätte ich halt noch die ADRESSE - dazu. Und wenn moeglich auch noch Kontaktdaten - wie die Webseite. -. nur für die Fälle in denen es eben eine gibt!? Da gibt es die verschieden Moeglichkeiten - z.b.

//node():  

D.h. nach allen XML Nodes “tag” suchen, die als Attribut k=“amenity” und v=“school” haben und dann

 /.. 

eben den Parent zurĂĽckbekommen. Wenn man dann die dann mit foreach durchgehst, dann eben nochmal die Subabfragen machen. (so Harald Hartmann im anderen Thread)

**Zum Ausgangsproblem: **Der untenstehende code gibt ca. 2100 records (oder Zeilen ) aus aber immer nur im Format

ich will halt mehr daten - auch wenn die tags nicht immer gefĂĽllt sind und dann mal was leer bleibt. Deine Methode ist auch sehr interessant. werde die heut Abend mal ausprobieren.

Finales Ziel ist: die POI-DATEN dann schlussendlich auf DB zu speichern - also lediglich Schulen mit den Daten wie
-Adresse
-Kontakt(Webseite)
-Kontakt(email ) - sofern vorhanden…

nochmals - Der untenstehende code gibt ca. 2100 records (oder Zeilen ) aus aber immer nur im Format


#2173: ID:2882477853  [51.6261198,-0.7349665]  Bowerdean Primary School

Bin halt noch am Ausprobieren wie es mit dem xpath-request geht - diesen zu erweitern…


<?php
$query = 'node
  ["addr:postcode"~"RM12"]
  (51.5557914,0.2118915,51.5673083,0.2369398);
   node
  (around:1000)
  ["amenity"~"fast_food"];
           out;';

$context = stream_context_create(['http' => [
    'method'  => 'POST',
    'header' => ['Content-Type: application/x-www-form-urlencoded'],
    'content' => 'data=' . urlencode($query),
]]);

$endpoint = 'http://overpass-api.de/api/interpreter';
libxml_set_streams_context($context);

$result = simplexml_load_file($endpoint);
printf("Query returned %2\$d node(s) and took %1\$.5f seconds.\n\n", microtime(true) - $start, count($result->node));
}



//
// 2.) Work with the XML Result
//

# get all school nodes with xpath
$xpath = '//node[tag[@k = "amenity" and @v = "school"]]';
$schools = $result->xpath($xpath);
printf("%d School(s) found:\n", count($schools));
foreach ($schools as $index => $school)
{
    # Get the name of the school (if any), again with xpath
    list($name) = $school->xpath('tag[@k = "name"]/@v') + ['(unnamed)'];
    printf("#%02d: ID:%' -10s  [%s,%s]  %s\n", $index, $school['id'], $school['lat'], $school['lon'], $name);
}


?>



Freu ich wieder von dir zu hoeren.

vg tagtheworld

hallo und guten Abend

habe mal nach der methode von dir versucht vozugehen - u. deinen code leicht abgeaendert

das ist für alle die untenstehenen BEREICHE im Grunde dasselbe: - Auffällig; die Resultate in der csv-ausgegebenen DATEI sind wie folgt:

Echte Ergebnisse sind so dass man im Promillebereich WERTE hat mit einer vollen Zeile. Irgendwas stimmt hier wohl nicht…

**
update: ** habe den code für die Abfrage der dänischen Schulen verbessert; jetzt sehen die Ergebnisse etwas besser aus;:

Wie oben gesagt - sehen die Ergebnisse etwas (!!!) besser aus.
So wie es aussieht - hab ich da einen systemat. Fehler eingebaut. So wie ich das unten gemacht hab - so geht das offenkundig nicht.

**Ende des updates:
**

denmark

luxembourg

hamburg:

mache ich hier etwas falsch??? Es kommen fast nur non-sense-Ergebnisse raus… Nichts richtig verwertbares…

Hi tagtheworld,

natürlich wird es oft so sein, dass du nicht alle der gewünschten Werte bekommst. Zum Beispiel gibt es sehr viele Schulen, bei denen keine Anschrift oder keine Webseite eingetragen ist. Du hast in diesen Fällen also nur die Geokoordinaten und muss ggf. die Anschrift selbst herausfinden - sofern du sie brauchst.
Beim Umwandeln nach CSV mit @lon und @lat holst du zudem alle nodes in die Liste, unabhängig davon, ob sie amenity=school haben.

Aber auch die Geokoordinaten werden dir fehlen fĂĽr alle Schulen, die nicht als node, sondern als way oder gar als Relation eingetragen sind. Um diese Koordinaten zu bekommen, kannst du relation- und way-Objekte in Nodes umwandeln (nach o.g. Schritt 3):

osmconvert schulen.o5m --all-to-nodes -o=schulen_nodes.o5m

Um sicherzustellen, dass du nun nicht aus Versehen Eingänge oder Kioske in den Daten hast, die zu einem Schul-way oder einer Schul-Relation gehören, solltest du am besten noch einmal filtern. Das läuft blitzschnell durch, keine Angst.

osmfilter schulen_nodes.o5m --keep=“amenity=school” -o=schulen_fertig.o5m

Jetzt kannst du mit Schritt 4b weitermachen.

hallo und guten Morgen Marqqs :slight_smile:

Wooooow! - Vielen Dank für die wertvollen u. sehr inspirierenden Erläuterungen - das hat mich weitergebracht. :):slight_smile:

Hab das gleich mal an einem File ausprobiert der nicht soo gross ist: Niederlande 900 MB

fĂĽr das Beispiel Niederlande: 3100 reslutate - bzw. Schulen.

wget http://download.geofabrik.de/europe/netherlands-latest.osm.pbf
./osmconvert netherlands-latest.osm.pbf -o=dutch.o5m
./osmfilter dutch.o5m --keep="amenity=school" -o=dutch-schools.o5m
./osmconvert dutch-schools.o5m --all-to-nodes -o=dutch-schools_nodes.o5m
./osmfilter dutch-schools_nodes.o5m --keep="amenity=school" -o=dutch-schools-results.o5m
./osmconvert dutch-schools-results.o5m --csv="name addr:city website" -o=dutch-schools-results.csv

das ist gut durchgelaufen - auch sehr schnell - und ich hatte hier schon Schwierigkeiten auf dem klienen notebook Da musste ich Dinge begrenzen limits einsetzen

http://forum.openstreetmap.org/viewtopic.php?id=25577

Das ist mir passiert als ich auf einem File von Baden Württemberg mit 284 mb gearbeitet habe (siehe den o.g. Thread). Gibt es hier eine Erklärung dafür. Grundsätlich denke ich dass ich die OSM-Dinge auf einem sehr viel leistungsfaehigeren Rechner machen muss. Das Aktelle: Samsunng q 210, 12,1" OpenSuse 13.1: Intel® Core™ 2 Duo Proz. P8400 2,26 GHz 1066 MHz FSB 3 MB

Zu dem aktuellen Versuch beim netherlands-latest - mit 900 mb.

Jetzt fehlen die geodaten lon u. lat. Was nicht so schlimm ist. Auffällig allerdings ist schon, dass im Grunde alle Strassennamen fehlen.

** Fragen: **

Hab ich denn den Ausdruck irgendwie falsch geschrieben hier:

kann man sehen, ob denn da grundsätzlich mehr (vorhanden) ist? - mit einem offeneren Abfrage - nach allen Tags - (also dann mülsste ich den o.g. Ausdruck - vor allen Dingen in den Punkt (en) vier aendern, oder!? - oder mit einer Abfrage via overpass api ?

BTW: mit einer xpath-Abfrage in PHP hab ich das schon mal durchgespielt - hier http://forum.openstreetmap.org/viewtopic.php?id=25905 Harald Hartmann hat mir dann dazu geraten:

Grundsätlich gefragt: allerdings ist der von dir vorgeschlagene Weg ein sehr sehr gutes Verfahren. Würde das gern in eine DB überführen. Und diese dann regelmässig
up-to-date zu halten. Was meinst du denn hierzu. Bin hier auf der Suche nach einem probaten Verfahren. Und dies sollte sich dann eignen die Daten versch. Länder abzufragen.
Deshalb arbeite u. versuche ich derzeit die verschiedenen Abfragemethoden durch - etwa osmconvert, php mit xpath oder auch mal andere…:Ziel: das efffizienteste Verfahren zu finden das am besten passt für meine Aufgabge.

Die osmconvert -/filter-Abfragen lassen sich m.E. sicher gut dazu verwenden. Brogo hat hier einiges dazu gepostet. http://wiki.openstreetmap.org/wiki/User:Brogo/OpenLayers_Datenbankanbindung

Freu mich wieder zu hoeren.

VG TagTheWorld:)

**
UPDATE**

was auffällt - nach dem ich spanien u die niederlande mal nach der og. methode durchgearbeitet habe: Es gibt bei dem Code nie (!!!) eine Strasse eine Hausnummer und nur im Promille-Bereich eine Stadt.

Warum ist das denn so!? ist da was falsch

**
spain:** 10 tausend records

cp *.csv data

**netherlands 3 tausend records
**

da stimmt noch irgend was nicht… in der letzten Zeile - denk ich mal…

Die Kernfrage scheint jene zu sein : wie baue ich einen korrekten request der die Adress-tags richtig u. korrekt fomuliert;: vgl auch hier.:

http://wiki.openstreetmap.org/wiki/Key:addr

Hast du denn dir mal zwischendurch die produzierten Dateien dutch-schools_nodes.o5m und dutch-schools-results.o5m genauer angeschaut, ob da noch addr: Elemente drin sind?

Schau doch mal mit einem Texteditor (nach Umwandlung in *.osm) oder benutze von osmfilter den Parameter --out-key … Details siehe OSM-Wiki dazu.

Moin!

Hm, ich verwende oft ein Notebook mit 32-bit-Atom-Prozessor und 2 GiB RAM. Also, sehr viel Rechenleistung brauchst du nicht. Im schlimmsten Fall dauert alles halt etwas länger. Wichtig ist aber, dass du genügen Hauptspeicher in der Kiste hast, unter 2 GiB würde ich da nicht anfangen.

Guck bitte nochmal genauer hin. Wenn du die Listenspalte “addr:street” nicht mit anforderst, wird im Ergebnis natürlich auch keine drin sein. Gleiches gilt für die Hausnummer…

Auch die Idee von Stephan finde ich gut!

Bei meinen Versuchen hat es sich bewährt, Testdaten mit ein paar wenigen Datensätzen im XML-Format (.osm) selbst zu fabrizieren und dann die ganze Toolchain drüberlaufen zu lassen. Geht viel schneller, und vor allem weiß man dann genau, was man als Ergebnis erwartet. Wenns geklappt hat, kann man mit “echten” Daten arbeiten.

hallo Stephan hallo Marqqs

vielen Dank für die Tipps - werde das alles behertzigen u. das mal näher ansehen. Auch nach mehr Tags werde ich aussschau halten.

ps - wie man sieht in den letzten TAGEN hat sich die statistik - und die angaben ĂĽber das Wachstum hier

https://taginfo.openstreetmap.org/tags/amenity=school

deutlich erhoeht

592852
592672
592443

doe werte _ u. das Wachstum ergeben sich innerhalb einer Woche. Mich interessiert hier bes. ; sind das absolutze WERTE - also neue Einträge - sozusagen ganz neue Records oder
koennnen das auch aenderungen sein!?

Freu mich wenn hier einer antworet.

vg

Hallo und guten Abend

binnen der letzen 9 Jahre hat sich doch jede Menge getan. Ich staune wie viel vor Jahren schon in Sachen Schule schon in OpenStreetmap verzeichnet ist -

Euch vielen Dank fĂĽr Eure tolle Arbeit hier.

VG TagTheWorld

Jo, und ich staune, dass jemand soooo lange Interesse an dem Thema Schule hat.

1 Like

naja - keine Ahnung wofür Dein Herz schlägt oder was dich so interessiert. Hier gibts ja im Grunde alles - einen ganzen Kosmos von Daten, Entities, items und Gegenstände für die man sich interessieren kann.

Also - mich interessiert die S schon länger - hatte im Übrigen auch eine tolle Schulzeit u. wünsch allen, dass sie das auch so erleben können.

Und wenn OpenStreetmap hier auch (nur etwas - also m.a.W. eine klitzekleine Kleinigkeit) dazu beitragen kann - dann wärs klasse.

Findest du das wirklich sooooo originell :wink: