Last active
February 28, 2024 15:39
-
-
Save 0187773933/3419dbf883f6b97a56bfb9a4f65bb6bd to your computer and use it in GitHub Desktop.
Convert Google Takeout Saved / Starred Places GeoJSON to KML File
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python3 | |
import sys | |
import json | |
from pygeoif.geometry import Point | |
from fastkml import kml | |
from pprint import pprint | |
from pathlib import Path | |
import googlemaps | |
from urllib.parse import urlparse , parse_qs , unquote | |
def write_json( file_path , python_object ): | |
with open( file_path , "w" , encoding="utf-8" ) as f: | |
json.dump( python_object , f , ensure_ascii=False , indent=4 ) | |
def read_json( file_path ): | |
with open( file_path ) as f: | |
return json.load( f ) | |
def write_kml( file_path , kml_object ): | |
with open( file_path , "w" ) as out_file: | |
out_file.write( kml_object.to_string( prettyprint=True ) ) | |
def get_nested( data , *args ): | |
if args and data: | |
element = args[ 0 ] | |
if element: | |
value = data.get( element ) | |
return value if len( args ) == 1 else get_nested( value , *args[ 1 : ] ) | |
return None | |
def is_lat_long_pair( search_term ): | |
try: | |
lat, lon = search_term.split(',') | |
lat = float(lat) | |
lon = float(lon) | |
return -90 <= lat <= 90 and -180 <= lon <= 180 | |
except ValueError: | |
return False | |
except Exception: | |
return False | |
# https://console.cloud.google.com/apis/library/geocoding-backend.googleapis.com?project=asdf | |
if __name__ == "__main__": | |
input_path = "./Saved Places.json" | |
if len( sys.argv ) > 1: | |
input_path = sys.argv[ 1 ] | |
input_path_posix = Path( input_path ) | |
parsed_output_path = str( input_path_posix.parent.joinpath( "parsed_saved_places.json" ) ) | |
kml_output_path = str( input_path_posix.with_suffix( ".kml" ) ) | |
gmaps = googlemaps.Client( key="asdf" ) | |
data = read_json( input_path ) | |
# parsed_places = read_json( parsed_output_path ) | |
# if not parsed_places: | |
# parsed_places = [] | |
parsed_places = [] | |
k = kml.KML() | |
folder = kml.Folder() | |
total = len( data[ "features" ] ) | |
for index , feature in enumerate( data[ "features" ] ): | |
print( f"Processing {index+1} of {total}" ) | |
# pprint( feature ) | |
latitude = feature[ "geometry" ][ "coordinates" ][ 0 ] | |
longitude = feature[ "geometry" ][ "coordinates" ][ 1 ] | |
address = get_nested( feature , "properties" , "location" , "address" ) or get_nested( feature , "properties" , "Location" , "Address" ) | |
country_code = get_nested( feature , "properties" , "location" , "country_code" ) | |
title = get_nested( feature , "properties" , "title" ) or get_nested( feature , "properties" , "Title" ) | |
name = get_nested( feature , "properties" , "location" , "name" ) or get_nested( feature , "properties" , "Location" , "Name" ) | |
google_maps_url = get_nested( feature , "properties" , "google_maps_url" ) | |
parsed_url = urlparse( google_maps_url ) | |
query_components = parse_qs( parsed_url.query ) | |
search_term = query_components.get( "q" , [ "" ] )[ 0 ] | |
# customer_id = query_components.get( "cid" , [ "" ] )[ 0 ] | |
geocode_result = False | |
if latitude == 0 and longitude == 0: | |
if search_term: | |
if is_lat_long_pair( search_term ): | |
latitude , longitude = search_term.split( "," ) | |
latitude = float( latitude ) | |
longitude = float( longitude ) | |
print( f"\tquery was lat/long pair : {latitude} || {longitude}" ) | |
else: | |
geocode_result = gmaps.geocode( search_term ) | |
latitude = geocode_result[ 0 ][ "geometry" ][ "location" ][ "lat" ] | |
longitude = geocode_result[ 0 ][ "geometry" ][ "location" ][ "lng" ] | |
print( f"\tgeocoded {search_term} to {latitude} || {longitude}" ) | |
else: | |
print( "\tno lat long , AND no search term ???" ) | |
print( "\tshould be impossible" ) | |
label = name or search_term or title or address or f"{latitude} || {longitude}" | |
parsed_place = { | |
"latitude": latitude, | |
"longitude": longitude, | |
"address": address, | |
"country_code": country_code, | |
"title": title, | |
"name": name, | |
"google_maps_url": google_maps_url, | |
"label": label | |
} | |
parsed_places.append( parsed_place ) | |
p = kml.Placemark() | |
p.name = label | |
p.description = f"{latitude} , {longitude}" | |
p.geometry = Point( latitude , longitude ) | |
folder.append( p ) | |
k.append( folder ) | |
write_kml( kml_output_path , k ) | |
write_json( parsed_output_path , parsed_places ) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment