Googleジオコードを解析する
-
06-07-2019 - |
質問
アプリでGoogleジオコーディングAPIを使用していますが、返された住所情報を確実に解析するのが難しいと感じています。誰かがライブラリを持っているか、情報を解析して、これを自分で書いてすべてのケースをカバーすることを防ぐことを望んでいます。
json apiを使用しており、住所行と座標を簡単に抽出できます データベースに保存しますが、問題は他のアドレス情報を信頼できる方法で抽出して保存できるようにすることです。
Googleがジオコーディングされたデータに使用するXAL構造化住所の仕様を見てきましたが、私の問題は、すべての国のすべての住所タイプに対応できるため、結果の解析が困難になることです。
郵便番号のような単純なものは、親タグの任意の組み合わせのかなり奥深くにネストできます。ある国の中でも、ツリーの表示方法はさまざまであるため、解析するのが予想よりも難しくなっています。
皮肉なことに、私の最終目的は、データベース内のツリー(rails acts_as_treeなど)に保存することです。これにより、ユーザーは後でアイテムを簡単に見つけることができます。たとえば、国、州、地域、町、郊外などをクリックします
レールで作業しています
解決
これをすべてカプセル化するgemとプラグインがあります。 GeoKit と呼ばれます。
Googleまたは他の少数のジオコーディングサービスプロバイダーを使用することができます。モデルに適切なフィールドがある場合は、距離の計算も実行できます(本当にすてきなことは、この計算がSQLで実行されることです)。
たとえば、本番アプリケーションの1つで長い間使用して、郵便番号間の距離を計算しています。既に述べたように、私はかなり長い間本番環境で使用しているので、コードの健全性について心配する必要はありません。
他のヒント
これを数回行いました。 (Googleの)サンプルコードは機能しますが、脆弱です。Googleから返されるジオコーディングデータは、せいぜい不完全で、一貫性がありません。
とにかく。すべてのジオコーダーはひどいですが、少なくともGoogleのものは無料で、他のジオコーダーよりもひどいです。ため息。以下を試してください。 Placemarkを渡す(getLocations AJAXメソッドが複数を返す場合があることに注意してください)と、結果を正規化します。豪華にしたい場合は、placemark.addressフィールドを使用します。場合によっては、個々のフィールドよりも多くの情報が含まれます。通常、ジオコーディングするために実際に送信したテキストのみが含まれます。
function Mark(placemark) {
this.latitude = 0.0;
this.longitude = 0.0;
this.accuracy = 0;
this.country = null;
this.region = null;
this.city = null;
this.postalCode = null;
this.street = null;
this.address = null;
this.placemark = placemark;
if (placemark) {
if (placemark.Point && placemark.Point.coordinates) {
this.latitude = placemark.Point.coordinates[0];
this.longitude = placemark.Point.coordinates[1];
}
var elem = placemark.AddressDetails;
if (elem) {
this.accuracy = elem.Accuracy;
if (elem.Country) {
elem = elem.Country;
this.country = elem.CountryNameCode;
}
if (elem.AdministrativeArea) {
elem = elem.AdministrativeArea;
this.region = elem.AdministrativeAreaName;
}
if (elem.SubAdministrativeArea) {
elem = elem.SubAdministrativeArea;
}
if (elem.Locality) {
elem = elem.Locality;
this.city = elem.LocalityName;
}
if (elem.PostalCode) {
this.postalCode = elem.PostalCode.PostalCodeNumber;
}
if (elem.Thoroughfare) {
this.street = elem.Thoroughfare.ThoroughfareName;
}
}
}
}