累積了幾年資料後,某次把資料提供給其他單位參考,還被抓出一堆錯務的經緯度,有些甚至在靠近北極的海上......之後才把經緯度加上了查驗
做法:
1.取出要轉的地址
2.經GOOGLE轉出經緯度
3.把轉回來的經緯度再次利用GOOGLE轉回一組新地址
4.將原地址與經由GOOGLE轉回來的新地址比對,如果原地址的縣市與鄉鎮同時存在於新地址的前十二個字,則認定縣市鄉鎮正確
5.GOOGLE傳回來的地址中,大部分的”臺”都是用”台”,所以在比對的時候有把轉回來的新地址中”台”替換成”臺”再比對
其中的url,http://maps.google.com//maps/api/geocode/json?address=是可以直接用的,後面可以帶的參數有很多,比如說在查地址的時候可以限定回傳的國家,或是在邊界的時候怎麼拚斷,以及回傳文字的語言。
在經緯度反查地址的時候,台灣記得要加上&language=zh-tw,不然傳回來的地址會是英文的
免費的用戶每天有2500筆,企業用戶有10萬筆,但不管免費或企業,google每秒都有設查詢次數限制,要注意
下面是地址查經緯度的部分,經緯度查地址其實是一模一樣的東西,這是第一版,後來有把兩個函式合併
可以留意一下GOOGLE回傳的json中包含"location_type"這個欄位,這是GOOGLE的精準度,共分成四個等級,節錄如下
location_type
會儲存指定位置的其他相關資料,目前所支援的值如下:"ROOFTOP"
表示傳回的結果是精準的地理編碼,因為結果中位置資訊的精確範圍已縮小至街道地址。"RANGE_INTERPOLATED"
表示傳回的結果反映的是插入在兩個精確定點之間 (例如十字路口) 的約略位置 (通常會在街道上)。如果 Geocoder 無法取得街道地址的精確定點地理編碼,就會傳回插入的結果。"GEOMETRIC_CENTER"
表示傳回的結果是結果的幾何中心,例如折線 (例如街道) 和多邊形 (區域)。"APPROXIMATE"
表示傳回的結果是約略位置。
以我個人的經驗,即使是最差的APPROXIMATE,縣市鄉鎮都有可能是對的,所以如果只是要求到縣市鄉鎮對,第四等級的經緯度還是可以用,但如果需要畫圖,比如說經銷商分布圖、公車站牌密度圖或是熱區,則不建議使用第三跟第四等級,因為他們會是幾何與約略位置,我的經驗是他們會集中在"某一點",造成錯誤的熱區或密度結果
/// <summary>
/// 地址查經緯度
/// </summary>
/// <param name="StrAddress">地址</param>
/// <param name="GoogleResult">回傳結果</param>
/// <param name="location_type">精準度</param>
/// <returns></returns>
public static double[] getLatLng(string StrAddress, out string GoogleResult, out string location_type)
{
string address = "";
string StrClientID = "填購買的google id";
string keyString = "填購買的google key";
//google地理服務的網址,下面這串網址就能直接用了
string urlString = "http://maps.google.com//maps/api/geocode/json?address=" + address + "&sensor=false&client=" + StrClientID;
//下面這步是企業用戶登入時要作的sign in
string StrCryptoKey = Sign(urlString, keyString);
var url = String.Format(StrCryptoKey);
string result = String.Empty;
HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(url);
using (var response = request.GetResponse())
using (StreamReader sr = new StreamReader(response.GetResponseStream()))
{
//Json格式: 請參考http://code.google.com/intl/zh-TW/apis/maps/documentation/geocoding/
result = sr.ReadToEnd();
}
//將Json字串轉成物件
GoogleGeocodingAPI.RootObject rootObj = JsonConvert.DeserializeObject<GoogleGeocodingAPI.RootObject>(result);
double lat, lng;
if (rootObj.status == "OK")
{
GoogleResult = "OK";
//從results開始往下找
lat = rootObj.results[0].geometry.location.lat;//緯度
lng = rootObj.results[0].geometry.location.lng;//經度
location_type = rootObj.results[0].geometry.location_type.ToString();
}
else
{
GoogleResult = rootObj.status;
lat = 0;
lng = 0;
location_type = "";
}
double[] latLng = { lat, lng };
return latLng;
}
下面是比對,想法是只要抓前半段地址比對就好,不需要抓到整個地址,再者由於在臺灣,GOOGLE傳回來的地址前面會有三碼郵遞區號跟"台灣"兩字,所以抓前12個字來比
如果縣市跟鄉鎮都命中就認為是對的
/// <summary>
/// 比對縣市鄉鎮有沒有包含在反查回來的地址
/// </summary>
/// <param name="city">縣市</param>
/// <param name="area">鄉鎮</param>
/// <param name="FixedAddress">地址</param>
/// <returns></returns>
public static bool CheckAddressCorrect(string city, string area, string FixedAddress)
{
bool result = false;
string address = "";
if (FixedAddress.Length > 12)
{ address = FixedAddress.Substring(0, 12); }
else
{ address = FixedAddress; }
//GOOGLE傳回來的地址會是"台" 不知到甚麼時候才會改回"臺",所以替換掉
FixedAddress = FixedAddress.Replace('台', '臺');
//高雄市三民區因業務需要,有分成三民東西區,替換掉
if (city == "高雄市" && area == "三民東區")
area = area.Replace("三民東區", "三民區");
if (city == "高雄市" && area == "三民西區")
area = area.Replace("三民西區", "三民區");
//比對縣市鄉鎮
if (FixedAddress.IndexOf(city, StringComparison.OrdinalIgnoreCase) > 0 && FixedAddress.IndexOf(area, StringComparison.OrdinalIgnoreCase) > 0)
{ result = true; }
return result;
}
大概就是這樣,我曾經碰過短時間內GOOGLE一直回傳"limit query"的錯誤訊息,不過過一下子就好了,與同事討論也無解,只能猜測是當時GOOGLE比較忙吧XD~
沒有留言:
張貼留言