Skip to content

Instantly share code, notes, and snippets.

@0187773933
Last active February 28, 2024 15:39
Show Gist options
  • Save 0187773933/3419dbf883f6b97a56bfb9a4f65bb6bd to your computer and use it in GitHub Desktop.
Save 0187773933/3419dbf883f6b97a56bfb9a4f65bb6bd to your computer and use it in GitHub Desktop.
Convert Google Takeout Saved / Starred Places GeoJSON to KML File
#!/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