automat. POI-export aus overpass-api via Perl XML::Twig und DBI

hallo und guten Abend,

ich habe bisher immer meine Daten von planet-files abgeleitet und dann in CSV-Dateien hinterlegt. Dabei war ich der Frage nachgegangen - ob ich in postgresql anfangen soll oder noch mit Mysql arbeiten kann. GGF ist dann ansonsten das Thema etwas zu groß für das was ich mache.

Deshalb hatte ich eine andere Überlegung und nun wollte ich Euch fragen, ob es gewisse Grundlagen dafür gibt mittels Perl an die overpass-Api zu kommen. Was mache ich in der Regel. In der Regel frage ich in den OSM-Daten nur bestimmte POI ab und mache daraus eine thematische Karte. In der einfachsten Anwendung wären das nur Nodes und bei Flächen wird ein Punkt generiert der dann die Daten bekommt - quasi eine Flächen->Node-Konvertierung.

Meine Überlegungen gehen nun dahin diese Daten nicht mehr in einer CSV vorzuhalten sondern in einer mySQL-Datenbank:

Gearbeitet hab ich mit dem folgenden Toolset: hier eine detailliere Übersicht über meine Ideen, Ansätze u.d Versuche mit den o.g. Techniken: https://wiki.openstreetmap.org/wiki/User:Tagtheworld

  • osmfilter - osmconvert

ein Bspl:


./osmconvert ein file aus deutschland ....osm --all-to-nodes --csv="@id @lon @lat amenity name" --out-csv -o=outfile.csv

und dann:


grep cafe outfile.csv > cafes.csv
grep restaurant outfile.csv > restaurants.csv
cat cafes.csv restaurants.csv > cafes_and_restaurants.csv

b. auf der anderern Hand koennte ich das ggf. auch so machen: mit der overpass-api:

untenstehend die beiden skripte:

die datei osm_to_db.pl ferner die datei create_db.pl

eine Ausgabe von overpass-api;

mysql.txt



<node id="2064639440" lat="49.4873181" lon="8.4710548">
    <tag k="amenity" v="restaurant"/>
    <tag k="cuisine" v="turkish"/>
    <tag k="email" v="info@lynso.de"/>
    <tag k="name" v="Kilim  - Café und Bar Restaurant"/>
    <tag k="opening_hours" v="Su-Th 17:00-1:00; Fr, Sa 17:00-3:00"/>
    <tag k="operator" v="Cengiz Kaya"/>
    <tag k="phone" v="06 21 - 43 755 371"/>
    <tag k="website" v="http://www.kilim-mannheim.de/"/>
  </node>
  <node id="2126473801" lat="49.4851170" lon="8.4756295">
    <tag k="amenity" v="restaurant"/>
    <tag k="cuisine" v="italian"/>
    <tag k="email" v="mannheim1@vapiano.de"/>
    <tag k="fax" v="+49 621 1259 779"/>
    <tag k="name" v="Vapiano"/>
    <tag k="opening_hours" v="Su-Th 10:00-24:00; Fr-Sa 10:00-01:00"/>
    <tag k="operator" v="Vapiano"/>
    <tag k="phone" v="+49 621 1259 777"/>
    <tag k="website" v="http://www.vapiano.de/newsroom/?store=29"/>
    <tag k="wheelchair" v="yes"/>
  </node>
 
 
  <node id="667927886" lat="49.4909673" lon="8.4764904">
    <tag k="addr:city" v="Mannheim"/>
    <tag k="addr:country" v="DE"/>
    <tag k="addr:housenumber" v="5"/>
    <tag k="addr:postcode" v="68161"/>
    <tag k="addr:street" v="Collinistraße"/>
    <tag k="amenity" v="restaurant"/>
    <tag k="name" v="Churrascaria Brasil Tropical"/>
    <tag k="phone" v="+496211225596"/>
    <tag k="wheelchair" v="limited"/>
  </node>


und dann hier der Code



#!/usr/bin/perl 
use strict ;
use DBI;
use XML::Twig;
 
# prepare database
my $dbh=dbh(); # connect
init();
$dbh->do('USE db123');
#$dbh->do('DELETE FROM pois');
 
# sql
my $sql = 'REPLACE INTO pois VALUES (?,?,?,?,?,?)';
my $sth = $dbh->prepare($sql);
 
# set up handler
my $t = XML::Twig->new( 
  twig_handlers => { 'node' => \&node }
);
 
# parse xml
my $xml = do { local $/; <DATA> };
$t->parse($xml);
#$t->parsefile('.osm');
 
sub node {
  my ($t,$elt) = @_;
 
  my %data=(
   'id'  => $elt->att('id'),
   'lat' => $elt->att('lat'),
   'lon' => $elt->att('lon'),
   );
  for my $tag ( $elt->children() ){
    $data{$tag->att('k')} = $tag->att('v');
    #print $tag->att('k').' = '.$tag->att('v')."\n";
  }
 
  # update database
  my @f = map{ $data{$_} }('id','lat','lon','name','amenity','operator');
  if ($f[3] ne '' && $f[4] ne '' && $f[5] ne ''){
    print "-- INSERT --\n".
    (join "\n",@f).
    "\n\n";
    $sth->execute(@f);
  }
}
 
 
sub init {
  $dbh-> do('CREATE DATABASE IF NOT EXISTS db123 
             DEFAULT CHARACTER SET latin1 
             COLLATE latin1_german2_ci');
  $dbh->do('USE db123');
  $dbh->do('CREATE TABLE IF NOT EXISTS pois (
           id       BIGINT(20) UNSIGNED NOT NULL,
           lat      FLOAT(10,7) NOT NULL,
           lon      FLOAT(10,7) NOT NULL,
           name     VARCHAR(255) COLLATE utf8_bin NOT NULL,
           amenity  VARCHAR(255) COLLATE utf8_bin NOT NULL,
           operator VARCHAR(255) COLLATE utf8_bin NOT NULL,
           PRIMARY KEY  (id)
          ) ENGINE=MyISAM DEFAULT 
            CHARSET=utf8 
            COLLATE=utf8_bin');
}
 
sub dbh {
  my $dsn = "DBI:mysql:database=;host=localhost";
  my $dbh = DBI->connect($dsn, 'user', 'pwd',
            {RaiseError => 1, PrintError => 1}) 
            or die (Error connecting " $DBI::errstr");
}


Zusatzüberlegungen :Den pois.osm file kann ich auch in die create_db.pl packen. Aber in der frühen Testphase ann ich auch ein Datei anlegen - etwa so /home/perl/OSM und die osm.pm dort hinlegen.
By the way: es sieht irgendwie danauch aus, als koennte ich osmDB.pm auch gut gebrauchen. Auserdem koennte ich noch Compress::Bzip2 installieren.

Meine neue Wiki-Page auf der ich mal die Moeglichen Lösungen zusammengestellt hab: https://wiki.openstreetmap.org/wiki/User:Tagtheworld

Hallo und guten Morgen! :slight_smile:

Es gibt immer viele mögliche Wege. Ein weiterer wäre mit dem sehr flexiblen Framework Osmium: https://wiki.openstreetmap.org/wiki/DE:Osmium

Falls du osmconvert und osmfilter verwendest, dann bitte zuerst filtern und erst danach osmconvert mit der Option --all-to-nodes starten. Andersrum ist die Aufgabe kaum zu bewältigen, das gilt auch für --all-to-nodes mit anschließendem grep. Außer natürlich, dein Kartenausschnitt ist wirklich sehr klein…

Schöne Grüße
Markus

hallo Markus

vielen Dank für deine schnelle Antwort. Ich werde mit Osmium am Wochenende ansehen. Damit habe ich noch nicht gearbeitet.

Vilen Dank !!:slight_smile:

Schoene Gruesse

Martin

Vielleicht hilft dir dies weiter: http://easyclasspage.de/maptools/seite-2.html

Gruß Klaus

also doch! Letztes Mal hast du geschrieben, das du nur mit reinen Textfeldern arbeitest. Spatiale Berechnungen - und sei es “nur” die Bestimmung des Mittelpunktes einer Fläche - gehen mit postgresql/postgis kinderleicht.

set center = st_centroid(way);

viel Spaß damit.

Gruss
walter

Oder auch mit Overpass API mit out center:


way({{bbox}})[leisure=pitch];out center;

Beispiel: http://overpass-turbo.eu/s/3FL

Edit: Beispiel vereinfacht…

Hallo Klaus, hallo Walter, hallo couchmapper

@ Klaus: werde mir OpenStreetMap - Overpass-Api Data Query auf jeden Fall ansehen. Denke mal dass das echt für mich wie gemacht ist.

@ Walter: Natürlich werde ich auch postgresql in Betracht ziehen.

Will alle Datenbank-Sachen auch auf postgresql aufsetzen (koennen), weil das langfristig eine gute Sache ist. Und weil - wie du Walter ja auch immmer wieder betonst - der Support hier super ist.

Ergo: ich will postgresql gern testen - einfach weil ich denke dass ich dass früher oder spaeter doch brauche - und dann auf die Basis einer PostgreSQL…
Der Vorteil einer mySQL (die ich im Moment nutze ) eben auch für kleine Projekte eine DB mit entsprechendem Interface aufzubauen um die im Moment gefragten Text-Daten zu erfassen.

Grüße
martin

welche Software setzt du denn bei solchen Projekten ein?

ich benutze Openlayers (javascript) als Client und “richtiges” Java für den Backend (OpenJDK) (Server).

Du wirst wohl Openlayers oder Leaflet für die Gui und perl/php für den Backend benutzen wollen. Damit ist ein Zugriff auf beide Datenbanken ebenfalls möglich, nur werde ich dir nicht viel helfen können.

Von dem Vorurteil “kleine Projekte → MySql , große Projekte → PostgreSQL” solltest du dich trennen - man kann beides mit beiden gut machen. Nur der ganze “Geo-Kram” geht mit PostGis wesentlich einfacher.

Gruss
walter

Habe bis dato eher mit PHP & MySQL Erfahrungen gesammelt.

Und jetzt bin ich soeben dabei, die overpass-api auf opensuse 13.1 zu installiern.

overpass Api:
Installation: http://overpass-api.de/full_installation.html
no frills: http://overpass-api.de/no_frills.html

ferner will ich demnächst noch mit folgendem arbeiten:

  • OSM::Tree
  • opaQuery.pl
  • OsmDB.pm

Dies deshalb weil sich diese Dinge - innerhalb einer generellen Unix-Philosphie von "vielen kleinen Programmen die man intelligent verkettet“ einsetzen lassen.

Will am kommenden WE auch noch PostgreSQL u. PostGis aufsetzen. Mal sehen ob das der Rechner mitmacht :wink: