Files
account_store/BaseModels/OpenStreetMap/osm_api.py
SDE eaab071a1e 0.1.42
not parse airports wo city
2023-08-07 23:45:10 +03:00

292 lines
9.2 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# -*- coding: utf-8 -*-
import time
import overpass
import copy
from geopy.geocoders import Nominatim
Nominatim_last_request = None
def osm_api_request(data, res_type):
time.sleep(1)
api = overpass.API(timeout=100)
res = api.get(data, responseformat=res_type)
pres_names = []
res_list = []
if res_type[:3].lower() == 'csv':
data_type_list = copy.deepcopy(res[0])
for line in res[1:]:
if line[0] in pres_names:
continue
i = 0
line_Dict = {}
while i < len(data_type_list):
line_Dict.update({data_type_list[i]: line[i]})
i += 1
if 'name:en' in line_Dict and 'name' in line_Dict:
if not line_Dict["name:en"]:
if line_Dict["name"]:
line_Dict["name:en"] = line_Dict["name"]
if not line_Dict["name:en"]:
continue
res_list.append(line_Dict)
pres_names.append(line[0])
else:
res_list = copy.deepcopy(res)
return res_list
def osm_get_area_id_by_params_dict(paramsDict):
area_id = None
try:
# Geocoding request via Nominatim
time.sleep(1)
geolocator = Nominatim(user_agent='TWB')
geo_results = geolocator.geocode(paramsDict, exactly_one=False, limit=3)
if not geo_results:
return area_id
# Searching for relation in result set
country_obj = None
for r in geo_results:
print(r.address, r.raw.get("osm_type"))
if r.raw.get("osm_type") == "relation":
country_obj = r
break
if not country_obj:
return area_id
# Calculating area id
area_id = int(country_obj.raw.get("osm_id")) + 3600000000
except Exception as e:
print(f'osm_get_area_id_by_params_dict Error = {e}')
return area_id
def osm_get_countries():
res_type = 'csv("name", "name:en", "name:ru", "ISO3166-1", "flag", "int_name", "official_name", "ISO3166-1:alpha3", ' \
'"ISO3166-1:numeric", ::lon, ::lat)'
data = 'relation["admin_level"="2"]["ISO3166-1:alpha3"~"^...$"]; ' \
'out center;'
res = osm_api_request(data, res_type)
from operator import itemgetter
res = sorted(res, key=itemgetter('name'))
return res
def osm_get_cities_by_country(country_Dict):
res = []
try:
if 'area_id' in country_Dict and country_Dict['area_id']:
area_id = country_Dict['area_id']
else:
return []
res_type = 'csv("name", "name:ru", "name:en", ::lon, ::lat)'
data = f'area({area_id})->.searchArea;' \
'(node[place~"city$|town$"](area.searchArea););' \
'out center;'
res = osm_api_request(data, res_type)
except Exception as e:
print(f'osm_get_cities_by_country Error = {e}')
return res
def osm_get_airports(area_id, city_find_str=None):
airports_cities_Dict = {}
try:
if not area_id:
return airports_cities_Dict
res_type = 'csv("name", "name:ru", "name:en", "iata", "icao", "place", "int_name", "addr:country", "city_served", ::lon, ::lat)'
data = f'area({area_id})->.searchArea;' \
f'nwr["aeroway"="aerodrome"]["iata"~"^...$"]["icao"~"^....$"]["abandoned"!~".*"]["landuse"!="military"]["was:landuse"!="military"]["aerodrome:type"!~"airfield|military|private"]["amenity"!="flight_school"]["closed"!="yes"](area.searchArea)->.airports;' \
if city_find_str:
data = f'{data}' \
f'foreach.airports->.elem(nwr(around.elem:20000)[{city_find_str}]->.city; .elem out center; .city out center;);'
else:
data = f'{data} .airports out center;'
res = osm_api_request(data, res_type)
if not city_find_str:
return res
present_IATA_list = []
i = 0
while i < len(res):
if not res[i]['iata'] or not res[i]['icao']:
del res[i]
continue
if res[i]['iata'] and res[i]['iata'] in present_IATA_list:
del res[i]
continue
present_IATA_list.append(res[i]['iata'])
# если аэропорт
if res[i]['iata']:
if i + 1 < len(res) and res[i+1]['place']:
# ищем город на следующих строках
i2 = i + 1
linked = None
while i2 < len(res) and res[i2]['place']:
if not linked:
if (res[i2]['name'] and res[i]['name'] and res[i2]['name'] in res[i]['name']) or \
(res[i2]['name:en'] and res[i]['name:en'] and res[i2]['name:en'] in res[i]['name:en']) or \
(res[i2]['name:ru'] and res[i]['name:ru'] and res[i2]['name:ru'] in res[i]['name:ru']):
linked = i2
i2 += 1
if not linked:
linked = i + 1
res[i]['city'] = copy.deepcopy(res[linked])
if not res[i]['city']['name'] in airports_cities_Dict:
airports_cities_Dict.update({res[i]['city']['name:en']: [res[i]]})
else:
airports_cities_Dict[res[i]['city']['name:en']].append(res[i])
while i < i2:
del res[i]
i2 -= 1
continue
# если не найдена связка с городом
elif res[i]['city_served']:
res[i]['city'] = {'name:en': res[i]['city_served']}
if not res[i]['city']['name:en'] in airports_cities_Dict:
airports_cities_Dict.update({res[i]['city']['name:en']: [res[i]]})
else:
airports_cities_Dict[res[i]['city']['name:en']].append(res[i])
del res[i]
continue
# текущий элемент - не аэропорт - удаляем
else:
del res[i]
continue
i += 1
if res:
airports_cities_Dict[None] = res
except Exception as e:
print(f'osm_get_airports Error = {e}')
if e.args[0] == 25:
return {'error': 'timeout'}
return airports_cities_Dict
def osm_get_country_w_cities_n_airports(country_Dict, area_id):
print(f'{country_Dict["name:en"]}')
if area_id:
country_Dict['area_id'] = area_id
else:
country_Dict['area_id'] = osm_get_area_id_by_params_dict({'country': country_Dict['name']})
airports_Dict = osm_get_airports(country_Dict['area_id'], 'place~"city$|town$"')
if airports_Dict and 'error' in airports_Dict and airports_Dict['error'] == 'timeout':
airports_Dict = osm_get_airports(country_Dict['area_id'], 'place="city"')
from ReferenceDataApp.funcs import get_countries_key_data, get_cities_by_country_name_en
db_cities = get_cities_by_country_name_en(country_Dict["name:en"])
cities = osm_get_cities_by_country(country_Dict)
for city in cities:
try:
print(f' > {city["name:en"]}')
except Exception as e:
print(str(e))
if airports_Dict and 'error' in airports_Dict and airports_Dict['error'] == 'timeout':
if city['name:en'] in db_cities.keys():
city['area_id'] = db_cities[city['name:en']]
else:
city['area_id'] = osm_get_area_id_by_params_dict(
{'country': country_Dict['name:en'], 'city': city['name:en']})
airports_list = osm_get_airports(city['area_id'])
if airports_list:
city['airports'] = copy.deepcopy(airports_list)
else:
if city['name:en'] in airports_Dict.keys():
city['airports'] = copy.deepcopy(airports_Dict[city['name:en']])
del airports_Dict[city['name:en']]
if not 'airports' in city:
city['airports'] = []
print(f' > > airports count={str(len(city["airports"]))}')
city['parsing_status'] = 'finished'
country_Dict['cities'] = cities
country_Dict['parsing_status'] = 'finished'
airports_wo_city = []
# if airports_Dict and None in airports_Dict:
# airports_wo_city = airports_Dict[None]
return country_Dict, airports_wo_city
def osm_get_countries_n_cities_n_airports():
airports_wo_city = []
from ReferenceDataApp.funcs import get_countries_key_data, get_cities_by_country_name_en
db_countries = get_countries_key_data()
countries = osm_get_countries()
i = 0
while i < len(countries):
area_id = None
if countries[i]['name:en'] in db_countries.keys():
area_id = db_countries[countries[i]['name:en']]
countries[i], airports_wo_city_for_country = osm_get_country_w_cities_n_airports(countries[i], area_id)
if airports_wo_city_for_country:
airports_wo_city.extend(airports_wo_city_for_country)
return countries