Computer >> บทช่วยสอนคอมพิวเตอร์ >  >> การเขียนโปรแกรม >> Python

คำนวณพิกัดภูมิศาสตร์ (Geocoding) ด้วย Google Maps Geocoding API ใน Python

ใช้ Google Maps Geocoding API แปลงชื่อสถานที่/ที่อยู่ → พิกัด latitude/longitude ด้วย Python requests และ json

ข้อกำหนดก่อนใช้งาน

  1. สร้าง Google Cloud Project
  2. Enable Geocoding API
  3. สร้าง API Key (Credentials → API Key)
  4. ตั้งค่า Billing (API ต้องมี billing account)

📖 รายละเอียด: Get API Key Guide

ติดตั้ง Library

pip install requests

โค้ดพื้นฐาน: Geocoding เดียว

import requests
import json

def geocode_address(address, api_key):
    """
    แปลงที่อยู่เป็นพิกัด (Latitude, Longitude)
    """
    url = "https://maps.googleapis.com/maps/api/geocode/json"
    params = {
        'address': address,
        'key': api_key
    }
    
    response = requests.get(url, params=params)
    data = response.json()
    
    if data['status'] == 'OK':
        result = data['results'][0]
        location = result['geometry']['location']
        formatted_address = result['formatted_address']
        
        return {
            'address': formatted_address,
            'latitude': location['lat'],
            'longitude': location['lng'],
            'place_id': result['place_id'],
            'location_type': result['geometry']['location_type']
        }
    else:
        raise Exception(f"Geocoding failed: {data['status']} - {data.get('error_message', '')}")

# ใช้งาน
if __name__ == "__main__":
    API_KEY = 'YOUR_API_KEY_HERE'  # ใส่ API Key ของคุณ
    place = input("Enter place name: ")
    
    try:
        result = geocode_address(place, API_KEY)
        print(f"Address: {result['address']}")
        print(f"Latitude: {result['latitude']}")
        print(f"Longitude: {result['longitude']}")
        print(f"Place ID: {result['place_id']}")
        print(f"Location Type: {result['location_type']}")
    except Exception as e:
        print(f"Error: {e}")

ตัวอย่างผลลัพธ์ (Dehradun, India):

Address: Dehradun, Uttarakhand, India
Latitude: 30.3164945
Longitude: 78.03219179999999
Place ID: ChIJr4jIVsMpCTkRmYdRMsBiNUw
Location Type: APPROXIMATE

โครงสร้าง JSON Response สำคัญ

{
  "results": [
    {
      "address_components": [...],
      "formatted_address": "Dehradun, Uttarakhand, India",
      "geometry": {
        "location": {
          "lat": 30.3164945,
          "lng": 78.0321918
        },
        "location_type": "APPROXIMATE",
        "viewport": {...},
        "bounds": {...}
      },
      "place_id": "ChIJr4jIVsMpCTkRmYdRMsBiNUw",
      "types": ["locality", "political"]
    }
  ],
  "status": "OK"
}

Status Codes ที่อาจพบ

Status ความหมาย
OKสำเร็จ มีผลลัพธ์
ZERO_RESULTSไม่พบที่อยู่
OVER_QUERY_LIMITเกิน quota (ต่อวัน/ต่อวินาที)
REQUEST_DENIEDAPI key ไม่ถูกต้อง หรือไม่ได้ enable API
INVALID_REQUESTพารามิเตอร์ขาดหาย (เช่น ไม่มี address)
UNKNOWN_ERRORServer error ลองใหม่อีกครั้ง

Reverse Geocoding: พิกัด → ที่อยู่

def reverse_geocode(lat, lng, api_key):
    url = "https://maps.googleapis.com/maps/api/geocode/json"
    params = {
        'latlng': f"{lat},{lng}",
        'key': api_key
    }
    response = requests.get(url, params=params)
    return response.json()

# ใช้งาน
result = reverse_geocode(30.3164945, 78.0321918, API_KEY)
if result['status'] == 'OK':
    print(result['results'][0]['formatted_address'])

Batch Geocoding: หลายที่อยู่พร้อมกัน

Google Geocoding API ไม่รองรับ batch โดยตรง ต้อง loop เอง (ระวัง rate limit)

import time

addresses = [
    "Bangkok, Thailand",
    "Chiang Mai, Thailand", 
    "Phuket, Thailand"
]

results = []
for addr in addresses:
    try:
        result = geocode_address(addr, API_KEY)
        results.append(result)
        print(f"✅ {addr}: {result['latitude']}, {result['longitude']}")
    except Exception as e:
        print(f"❌ {addr}: {e}")
    time.sleep(0.1)  # Respect rate limit (50 requests/second)

Best Practices

  • Cache ผลลัพธ์: บันทึกลง database ไม่ต้อง call API ซ้ำ
  • Rate Limiting: Free tier = 40,000 requests/month, 50 req/sec
  • Error Handling: ตรวจสอบ status ทุกครั้ง
  • API Key Security: ใช้ environment variables, ห้าม commit ลง git
  • Component Filtering: จำกัดประเภทผลลัพธ์ด้วย components parameter

ตัวอย่าง: Component Filtering (เฉพาะประเทศไทย)

params = {
    'address': 'Sukhumvit',
    'key': API_KEY,
    'components': 'country:TH'  # จำกัดเฉพาะประเทศไทย
}

ทางเลือกอื่น (Free Alternatives)

Service Free Tier หมายเหตุ
Nominatim (OpenStreetMap)Unlimited (with rate limit 1 req/sec)ต้องใส่ User-Agent, ใช้สำหรับ non-commercial
LocationIQ10,000 req/dayต้องสมัคร API key
OpenCage Geocoder2,500 req/dayรองรับ forward + reverse
Mapbox Geocoding100,000 req/monthต้องสมัคร

ตัวอย่าง Nominatim (ไม่ต้อง API Key)

import requests

def nominatim_geocode(address):
    url = "https://nominatim.openstreetmap.org/search"
    params = {
        'q': address,
        'format': 'json',
        'limit': 1
    }
    headers = {'User-Agent': 'MyApp/1.0 (myemail@example.com)'}
    response = requests.get(url, params=params, headers=headers)
    data = response.json()
    if data:
        return float(data[0]['lat']), float(data[0]['lon'])
    return None

print(nominatim_geocode("Bangkok, Thailand"))