Created
March 17, 2023 15:38
-
-
Save stelf/a069b9237140edfbb8b220195b6d9f70 to your computer and use it in GitHub Desktop.
geocoding a source CVS with google maps and then feed into a table in PostGIS
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
# geocoding a source CVS with google maps | |
# and then feed into a table in PostGIS | |
# | |
# interestingly some parts of the code were created with ChatGPT4 | |
# but the output, of course, had to be revised a little | |
# | |
# license CC-Attribution | |
3 | |
import csv | |
import requests | |
import psycopg2 | |
from psycopg2.extras import execute_values | |
from pyproj import Transformer | |
# Read the CSV file | |
def read_csv(file_path): | |
addresses = [] | |
with open(file_path, newline='', encoding='utf-8') as csvfile: | |
reader = csv.DictReader(csvfile) | |
for row in reader: | |
addresses.append(row) | |
return addresses | |
# Geocode an address using Google Maps API | |
def geocode(address, city, country, api_key): | |
url = f'https://maps.googleapis.com/maps/api/geocode/json?address={address},{city},{country}&key={api_key}' | |
response = requests.get(url) | |
data = response.json() | |
if data['status'] == 'OK': | |
location = data['results'][0]['geometry']['location'] | |
return location['lat'], location['lng'] | |
else: | |
return None | |
# Transform coordinates from EPSG:4326 to EPSG:4258 | |
def transform_coords(lat, lng): | |
transformer = Transformer.from_crs("EPSG:4326", "EPSG:7801", always_xy=True) | |
x, y = transformer.transform(lng, lat) | |
return f"POINT({x} {y})" | |
# Connect to the PostGIS database | |
def connect_to_db(database, user, password, host, port): | |
connection = psycopg2.connect(database=database, user=user, password=password, host=host, port=port) | |
return connection | |
# Insert data into PostGIS database | |
def insert_into_postgis(connection, data): | |
cursor = connection.cursor() | |
# Create table if not exists | |
create_table_query = """ | |
CREATE TABLE IF NOT EXISTS geocoded_addresses ( | |
id SERIAL PRIMARY KEY, | |
address VARCHAR(255), | |
city VARCHAR(255), | |
country VARCHAR(255), | |
location GEOMETRY(Point, 7801) | |
); | |
""" | |
cursor.execute(create_table_query) | |
# Insert data into the table | |
query = """ | |
INSERT INTO geocoded_addresses (address, city, country, location) | |
VALUES %s; | |
""" | |
execute_values(cursor, query, data) | |
connection.commit() | |
cursor.close() | |
# Main function | |
def main(): | |
# Replace these values with your own | |
csv_file_path = 'yourdata/input.csv' | |
google_api_key = 'yourkey' | |
postgis_config = { | |
'database': 'yourdb', | |
'user': 'youruser', | |
'password': 'yourpass', | |
'host': 'your.host.com', | |
'port': '5432', | |
} | |
addresses = read_csv(csv_file_path) | |
geocoded_data = [] | |
for address in addresses: | |
coords = geocode(address['address'], address['city'], address['countryCode'], google_api_key) | |
if coords: | |
wktcoords = transform_coords(*coords) | |
geocoded_data.append((address['address'], address['city'], address['countryCode'], wktcoords)) | |
connection = connect_to_db(**postgis_config) | |
insert_into_postgis(connection, geocoded_data) | |
connection.close() | |
if __name__ == '__main__': | |
main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment