Skip to content

Instantly share code, notes, and snippets.

@gitfvb
Created January 24, 2017 09:01
Show Gist options
  • Save gitfvb/2c5b99bdc9a1084868f1d6d1c8b51224 to your computer and use it in GitHub Desktop.
Save gitfvb/2c5b99bdc9a1084868f1d6d1c8b51224 to your computer and use it in GitHub Desktop.
GeoCoding with OSM, Bing and Google through the PowerShell - no addon needed
# https://msdn.microsoft.com/en-us/library/dn894107.aspx
<#
.Synopsis
This function uses the Google Maps API to Geocode an address.
.DESCRIPTION
This function uses the Google Maps API to Geocode an address by sending a web request to the API and then processes the resulting XML file for the longitude & latitude. The Google API has a threshold and when violated, you get an OVER_QUERY_LIMIT error based on the number of calls made per second and per day. If the function encounters this error it will pause for 2 seconds and throw a warning. If two subsequent calls fail, then the daily max call may have been reached and it will error out.
.EXAMPLE
PS C:\> "7171 Southwest Parkway, Austin, TX" | Get-GeoCode
Address Latitude Longitude
------- -------- ---------
7171 Southwest Parkway, Austin, TX 30.2510727 -97.8631899
.EXAMPLE
PS C:\> $Addresses = "Baltimore, MD", "Washington, DC"
PS C:\> $Addresses | Get-GeoCode
Address Latitude Longitude
------- -------- ---------
Baltimore, MD 39.2903848 -76.6121893
Washington, DC 38.9071923 -77.0368707
#>
$Addresses = @("Address1")
$Addresses += "Address2"
$Addresses += "Address3"
Get-ChildItem C:\Test | Select-Object Name, CreationTime, @{Name="Kbytes";Expression={$_.Length / 1Kb}}
Import-Csv postfil_adressen.csv |
Select-Object *,@{Name='column3';Expression={'setvalue'}} |
Export-Csv file.csv -NoTypeInformation
Get-GeoCode -Address $Addresses -Provider "osm"
Get-GeoCode -Address $Addresses -Provider "bing"
Get-GeoCode -Address $Addresses -Provider "google"
function Get-GeoCode() {
param(
[String[]] $Address,
[String] $Provider
)
$i = 0
While ( $i -lt $Address.Count )
{
if ( $FailureCount -ge 2 )
{
Write-Error "You have called the Google Maps API too frequently and this has failed. Wait 24 hours and try again."
break
}
$AddressToken = $Address[$i]
$Parameter = "address=" + $AddressToken.Replace(" ","%20")
switch ( $Provider )
{
"bing" {
# TODO: den Token noch als Variable speichern
# http://dev.virtualearth.net/REST/v1/Locations/1%20Microsoft%20Way%20Redmond%20WA%2098052?include=queryParse&o=xml&key={bingkey}
$ApiUri = "http://dev.virtualearth.net/REST/v1/Locations/$($AddressToken.Replace(" ","%20"))?include=queryParse&o=xml&key={bingkey}"
$Response = Invoke-WebRequest -Uri $ApiUri
$ResponseXml = [xml]($Response.Content.Substring(1).Replace('"',"'"))
$ResponseStatus = $ResponseXml.Response.StatusDescription -eq "OK"
}
"google" {
# https://maps.googleapis.com/maps/api/geocode/json?address={{ADDRESS}}%20{{POSTCODE}}%20{{TOWN}}%20Germany&key={googlekey}
$ApiUri = "https://maps.googleapis.com/maps/api/geocode/xml?$($Parameter)"
$Response = Invoke-WebRequest -Uri $ApiUri
$ResponseXml = [xml]($Response.Content)
$ResponseStatus = $ResponseXml.GeocodeResponse.status -eq "OK"
}
"osm" {
# http://nominatim.openstreetmap.org/search?street={{ADDRESS}}&city={{TOWN}}&postalcode={{POSTCODE}}&countrycodes=de&format=json&polygon=1&addressdetails=1
# http://nominatim.openstreetmap.org/search?street=kaiserstrasse%2035&city=Frankfurt&postalcode=60329&countrycodes=de&format=json&polygon=1&addressdetails=1
# http://nominatim.openstreetmap.org/search?q=kaiserstrasse%2035,%20Frankfurt,%2060329&countrycodes=de&format=xml&addressdetails=1&limit=1
$ApiUri = "http://nominatim.openstreetmap.org/search?q=$($AddressToken.Replace(" ","%20"))&countrycodes=de&format=xml&addressdetails=1&limit=1"
$Response = Invoke-WebRequest -Uri $ApiUri
$ResponseXml = [xml]($Response.Content)
# TODO hier noch checken, wie ok festgestellt werden kann
#$ResponseStatus = $ResponseXml.GeocodeResponse.status -eq "OK"
$ResponseStatus = $TRUE
}
default {
}
}
if ( $ResponseStatus -eq $TRUE )
{
switch ( $Provider )
{
"bing" {
$lat = $ResponseXml.Response.ResourceSets.ResourceSet.Resources.Location.Point.Latitude
$lon = $ResponseXml.Response.ResourceSets.ResourceSet.Resources.Location.Point.Longitude
}
"google" {
$lat = $ResponseXml.GeocodeResponse.result.geometry.location.lat
$lon = $ResponseXml.GeocodeResponse.result.geometry.location.lng
}
"osm" {
$lat = $ResponseXml.searchResults.place.lat
$lon = $ResponseXml.searchResults.place.lon
}
default { }
}
$ObjectHash = [ordered]@{ Provider = $Provider; Address = $AddressToken; Latitude = $lat; Longitude = $lon }
New-Object -TypeName PSObject -Property $ObjectHash
#Write-Host "Coordinates for '$AddressToken': '$ObjectHash' "
# It worked. Move to the next element and reset the failure count
$i++
$FailureCount = 0
}
elseif ( $ResponseXml.GeocodeResponse.status -eq "OVER_QUERY_LIMIT" )
{
Write-Warning "Too many calls to the Google API. Pausing for 2 seconds..."
$FailureCount++
Start-Sleep -Seconds 2
}
else
{
Write-Host "Failed to get GeoCode for '$Address' and continuing." -ForegroundColor Red
$i++
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment