Created
January 24, 2017 09:01
-
-
Save gitfvb/2c5b99bdc9a1084868f1d6d1c8b51224 to your computer and use it in GitHub Desktop.
GeoCoding with OSM, Bing and Google through the PowerShell - no addon needed
This file contains 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
# 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