feat: Add Overpass API integration for animal shelter data retrieval
This commit is contained in:
@@ -1,16 +1,21 @@
|
|||||||
import argparse
|
import argparse
|
||||||
import json
|
|
||||||
import os
|
import os
|
||||||
import requests
|
import requests
|
||||||
|
# TODO: consider using OSMPythonTools instead of overpass
|
||||||
|
import overpass
|
||||||
from tqdm import tqdm
|
from tqdm import tqdm
|
||||||
|
|
||||||
DEFAULT_OSM_DATA_FILE = "export.geojson"
|
DEFAULT_OSM_DATA_FILE = "export.geojson"
|
||||||
|
# Search area must be the official name, e.g. "Germany" is not a valid area name in Overpass API
|
||||||
|
# Consider instead finding & using the code within the query itself, e.g. "ISO3166-1"="DE"
|
||||||
|
DEFAULT_OVERPASS_SEARCH_AREA = "Deutschland"
|
||||||
|
|
||||||
|
|
||||||
def parse_args():
|
def parse_args():
|
||||||
"""Parse command-line arguments."""
|
"""Parse command-line arguments."""
|
||||||
parser = argparse.ArgumentParser(description="Upload animal shelter data to the Notfellchen API.")
|
parser = argparse.ArgumentParser(description="Download animal shelter data from the Overpass API to the Notfellchen API.")
|
||||||
parser.add_argument("--api-token", type=str, help="API token for authentication.")
|
parser.add_argument("--api-token", type=str, help="API token for authentication.")
|
||||||
|
parser.add_argument("--area", type=str, help="Area to search for animal shelters (default: Deutschland).")
|
||||||
parser.add_argument("--instance", type=str, help="API instance URL.")
|
parser.add_argument("--instance", type=str, help="API instance URL.")
|
||||||
parser.add_argument("--data-file", type=str, help="Path to the GeoJSON file containing (only) animal shelters.")
|
parser.add_argument("--data-file", type=str, help="Path to the GeoJSON file containing (only) animal shelters.")
|
||||||
return parser.parse_args()
|
return parser.parse_args()
|
||||||
@@ -21,13 +26,15 @@ def get_config():
|
|||||||
args = parse_args()
|
args = parse_args()
|
||||||
|
|
||||||
api_token = args.api_token or os.getenv("NOTFELLCHEN_API_TOKEN")
|
api_token = args.api_token or os.getenv("NOTFELLCHEN_API_TOKEN")
|
||||||
|
# TODO: document new environment variable NOTFELLCHEN_AREA
|
||||||
|
area = args.area or os.getenv("NOTFELLCHEN_AREA", DEFAULT_OVERPASS_SEARCH_AREA)
|
||||||
instance = args.instance or os.getenv("NOTFELLCHEN_INSTANCE")
|
instance = args.instance or os.getenv("NOTFELLCHEN_INSTANCE")
|
||||||
data_file = args.data_file or os.getenv("NOTFELLCHEN_DATA_FILE", DEFAULT_OSM_DATA_FILE)
|
data_file = args.data_file or os.getenv("NOTFELLCHEN_DATA_FILE", DEFAULT_OSM_DATA_FILE)
|
||||||
|
|
||||||
if not api_token or not instance:
|
if not api_token or not instance:
|
||||||
raise ValueError("API token and instance URL must be provided via environment variables or CLI arguments.")
|
raise ValueError("API token and instance URL must be provided via environment variables or CLI arguments.")
|
||||||
|
|
||||||
return api_token, instance, data_file
|
return api_token, area, instance, data_file
|
||||||
|
|
||||||
|
|
||||||
def get_or_none(data, key):
|
def get_or_none(data, key):
|
||||||
@@ -68,16 +75,35 @@ def https(value):
|
|||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
# TODO: take note of new get_overpass_result function which does the bulk of the new overpass query work
|
||||||
|
def get_overpass_result(area):
|
||||||
|
"""Build the Overpass query for fetching animal shelters in the specified area."""
|
||||||
|
api = overpass.API()
|
||||||
|
result = api.get(f"""
|
||||||
|
// fetch area to search within
|
||||||
|
area[name="{area}"]->.searchArea;
|
||||||
|
// gather results
|
||||||
|
nwr["amenity"="animal_shelter"](area.searchArea);
|
||||||
|
""", verbosity="geom"
|
||||||
|
)
|
||||||
|
return result
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
api_token, instance, data_file = get_config()
|
api_token, area, instance, data_file = get_config()
|
||||||
|
# Query shelters
|
||||||
|
overpass_result = get_overpass_result(area)
|
||||||
|
if overpass_result is None:
|
||||||
|
print("Error: get_overpass_result returned None")
|
||||||
|
return
|
||||||
|
print(f"Response type: {type(overpass_result)}")
|
||||||
|
print(f"Response content: {overpass_result}")
|
||||||
|
|
||||||
# Set headers and endpoint
|
# Set headers and endpoint
|
||||||
endpoint = f"{instance}/api/organizations/"
|
endpoint = f"{instance}/api/organizations/"
|
||||||
h = {'Authorization': f'Token {api_token}', "content-type": "application/json"}
|
h = {'Authorization': f'Token {api_token}', "content-type": "application/json"}
|
||||||
|
|
||||||
with open(data_file, encoding="utf8") as f:
|
for idx, tierheim in tqdm(enumerate(overpass_result["features"])):
|
||||||
d = json.load(f)
|
|
||||||
|
|
||||||
for idx, tierheim in tqdm(enumerate(d["features"])):
|
|
||||||
|
|
||||||
if "name" not in tierheim["properties"].keys() or "addr:city" not in tierheim["properties"].keys():
|
if "name" not in tierheim["properties"].keys() or "addr:city" not in tierheim["properties"].keys():
|
||||||
continue
|
continue
|
||||||
|
Reference in New Issue
Block a user