diff options
Diffstat (limited to 'ishtar_common/scripts/import_towns_from_osm.py')
| -rwxr-xr-x | ishtar_common/scripts/import_towns_from_osm.py | 110 | 
1 files changed, 110 insertions, 0 deletions
| diff --git a/ishtar_common/scripts/import_towns_from_osm.py b/ishtar_common/scripts/import_towns_from_osm.py new file mode 100755 index 000000000..fb301f09f --- /dev/null +++ b/ishtar_common/scripts/import_towns_from_osm.py @@ -0,0 +1,110 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +""" +Import towns from OpenStreetMap data. +Take an OSM xml file for argument. + +To get an OSM file (with a bounding box adapted to your needs): +curl --location --globoff "http://www.informationfreeway.org/api/0.6/node[place=village|town|city][bbox=-5.53711,41.90228,8.96484,51.50874]" -o city.osm +or from a whole xml/pbf export: +./osmosis --read-pbf ~/france-20110125.osm.pbf --node-key-value keyValueList="place.village,place.town,place.city" --write-xml city.osm +""" + +import sys +sys.path.append('.') + +from django.core.management import setup_environ +from django.core.exceptions import ObjectDoesNotExist +from django.contrib.gis.geos import Point +import settings + +setup_environ(settings) + +from optparse import OptionParser +from xml.parsers import expat + +from ishtar_base import models + +usage = "usage: %prog osm_file.xml" +parser = OptionParser(usage=usage) + +(options, args) = parser.parse_args() + +try: +    assert len(args) == 1 +except AssertionError: +    parser.error("You must provide one XML file") + + +ATTRS = [u"lat", u"lon"] + +# key : (mandatory, [restraint to keys]) +TAGS = {u"place":(True, [u"village", u"town", u"city"]), +        u"ref:INSEE":(True, []), +        u"population":(False, []) +        } + +class TownParser: + +    def __init__(self): +        self._parser = expat.ParserCreate() +        self._parser.returns_unicode = True +        self._parser.StartElementHandler = self.start +        self._parser.EndElementHandler = self.end +        self._parser.CharacterDataHandler = self.data +        self.town = {} +        self.number = 0 + +    def feed(self, data): +        self._parser.ParseFile(data) + +    def close(self): +        self._parser.Parse("", 1) # end of data +        del self._parser # get rid of circular references + +    def start(self, tag, attrs): +        if tag == u"node": +            self.town = {} +            for attr in ATTRS: +                if attr in attrs: +                    self.town[attr] = attrs[attr] +        if tag == u"tag": +            if not u"k" in attrs or not u"v" in attrs: +                return +            if attrs[u"k"] in TAGS: +                limit = TAGS[attrs[u"k"]][1] +                if limit and \ +                   (attrs[u"v"] not in limit or \ +                   (type(limit) == unicode and limit not in attrs[u"v"])): +                    self.town["DEL"] = True +                    return +                self.town[attrs[u"k"]] = attrs[u"v"] + +    def end(self, tag): +        if tag == u"node" and self.town and "DEL" not in self.town: +            for k in TAGS: +                if TAGS[k][0] and k not in self.town: +                    return +            self.number += 1 +            try: +                town = models.Town.objects.get(numero_insee=self.town["ref:INSEE"]) +            except ObjectDoesNotExist: +                return +            town.center = Point(float(self.town['lon']), float(self.town['lat']), +                                srid=4326) +            town.save() +            print town, "updated" + +    def data(self, data): +        pass + +p = TownParser() + +try: +    p.feed(file(args[0])) +    print u"%d towns updated" % p.number +except (IOError, expat.ExpatError): +    parser.error("Incorrect XML file") + + | 
