diff options
author | Étienne Loks <etienne.loks@peacefrogs.net> | 2011-01-27 18:08:13 +0100 |
---|---|---|
committer | Étienne Loks <etienne.loks@peacefrogs.net> | 2011-01-27 18:08:13 +0100 |
commit | 855505d64581ffd3601fd97defb02817926e14be (patch) | |
tree | c836b2e7230624a797d913c4114be68355027acd | |
parent | 95fa295d7d93cdb65755e66c559a792edec4f17a (diff) | |
download | Ishtar-855505d64581ffd3601fd97defb02817926e14be.tar.bz2 Ishtar-855505d64581ffd3601fd97defb02817926e14be.zip |
Add a script to import town from OpenStreetMap (closes #148)
-rwxr-xr-x | ishtar/scripts/import_towns_from_osm.py | 110 |
1 files changed, 110 insertions, 0 deletions
diff --git a/ishtar/scripts/import_towns_from_osm.py b/ishtar/scripts/import_towns_from_osm.py new file mode 100755 index 000000000..6c5698b4b --- /dev/null +++ b/ishtar/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 furnitures 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") + + |