import os import shutil import subprocess import zipfile from urllib import request, parse import atoma import requests atom_urls = { 'parcels': 'http://www.catastro.minhap.es/INSPIRE/CadastralParcels/ES.SDGC.CP.atom.xml', 'buildings': 'http://www.catastro.minhap.es/INSPIRE/buildings/ES.SDGC.BU.atom.xml', 'addresses': 'http://www.catastro.minhap.es/INSPIRE/Addresses/ES.SDGC.AD.atom.xml' } def format_codmun(provincia, municipio): """Obtiene el código de municipio a partir de la provincia y el municipio""" return str(provincia).zfill(2) + str(municipio).zfill(3) def parse_url(url): """Codifica la URL. parse.quote('abc def') -> 'abc%20def'""" url = parse.urlsplit(url) url = list(url) url[2] = parse.quote(url[2]) parsed_url = parse.urlunsplit(url) return parsed_url def download_and_process_municipality(url, epsg, output_gpkg, to_epsg=None): """ Descarga un gml de catastro a partir de una url y un epgs. Lo convierte a geopackage. Permite declarar un epsg de destino. """ if not to_epsg: to_epsg = epsg try: try: os.makedirs('downloads') except: pass filename, headers = request.urlretrieve(url) with zipfile.ZipFile(os.path.join(filename), "r") as z: z.extractall(path=os.path.join(os.curdir, 'downloads')) for gml in os.listdir('downloads'): if os.path.splitext(gml)[1] == '.gml': layer_name = gml.split('.')[5] ogr_cmd = """ogr2ogr -update -append -f GPKG -s_srs EPSG:{} -t_srs EPSG:{} -lco IDENTIFIER={} {} {}""" \ .format(epsg, to_epsg, layer_name, output_gpkg + '.gpkg', os.path.join('downloads', gml)) # print ("\n Executing: ", ogr_cmd) subprocess.run(ogr_cmd, shell=True, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) except Exception as e: print("Error: {}".format(str(e))) finally: shutil.rmtree('downloads') def get_municipality_atoms_url(atom_url, codmun=None): """ Lee el atom específico para cada parroquia. Devuelve el url del Atom de cada municipio con su epsg. Se puede pasar un parámetro codmun para devolver sólo este municipio. """ response = requests.get(atom_url) feed = atoma.parse_atom_bytes(response.content) urls = [] for entry in feed.entries: url = parse_url(entry.links[0].href) epsg = entry.categories[0].term.split('/')[-1] codmun_atom = os.path.basename(url).split('.')[4] if codmun is None or codmun == codmun_atom: urls.append((url, epsg)) return urls def get_provinces_atoms_url(url, province_code=None): """ Lee el atom general de Catastro Inspire que contiene los diferentes Atoms para cada provincia. Devuelve una lista con url a los atoms y el título. """ response = requests.get(url) feed = atoma.parse_atom_bytes(response.content) atoms_provincias = [] for entry in feed.entries: if province_code is not None: if os.path.basename(entry.links[0].href).split('.')[3] == 'atom_{}'.format(str(province_code).zfill(2)): url = parse_url(entry.links[0].href) title = entry.title.value atoms_provincias.append((url, title)) else: url = parse_url(entry.links[0].href) title = entry.title.value atoms_provincias.append((url, title)) return atoms_provincias def download(data_to_download, provincia=None, municipio=None, srs=None, filename="buildings", separar_salida=False): atoms_provincias = get_provinces_atoms_url(data_to_download, provincia) codmun = format_codmun(provincia, municipio) if municipio is not None else None geopackage_name = filename current_prov = 0 total_prov = len(atoms_provincias) for atom in atoms_provincias: current_prov += 1 prov_title = atom[1] prov_url = atom[0] print(prov_title) urls = get_municipality_atoms_url(prov_url, codmun=codmun) current_mun = 0 total_mun = len(urls) for url in urls: current_mun += 1 print('[{}/{}][{}/{}] Downloading {}'.format(current_prov, total_prov, current_mun, total_mun, url[0])) if separar_salida: geopackage_name = '_'.join([filename, prov_title.replace(' ', '_')]) download_and_process_municipality(url[0], url[1], geopackage_name, to_epsg=srs)