มี Latitude Longitude หาตำบล อำเภอ จังหวัด Google Maps API (Geocoding API)

อันนี้เป็น Note กันลืมสำหรับตัวเอง …

เรื่องก็คือว่า ได้โจทย์มาว่า มี Latitude และ Longitude ของลูกค้าแต่ละราย ที่ได้จากการเข้าเยี่ยม Check-in ของพนักงานขาย และทางเราต้องการระบุว่า ลูกค้ารายนี้อยู่ ตำบล อำเภอ และจังหวัดอะไร เพื่อทำการจัดกลุ่ม ลูกค้า และทำ Strategics ต่อไป …

พอได้โจทย์ และ Data มาก็เอาไปถาม ChatGPT 555+😂

คำตอบที่ออกมา กว่าจะงมและประกอบกันได้ตามต้องการ ก็ประมาณนี้ จ้า …

🛠 Tools ที่ใช้ หลัก 🛠

  1. Google Colab (ฟรี) > 👨‍💻Code_Python ฉบับเต็ม
  2. Google clould platform > Google Maps API (Geocoding API) (ใช้Free trial ได้ ฿20,465 credits used )

🏁 มา…เริ่มกันเลย ! 🤸‍♂️

ขั้นแรกต้องมี Google Cloud Account ก่อน ให้เรา ไปที่ ⇒ Google Cloud
⇒ เเล้วกด “Start free”

คลิกที่ “view expiration details” จะเห็น รายละเอียด Remaining 

โอเค ทีนี้เราก็มี Google Clould เเล้ว มาเริ่มสร้าง API กันเลย

การสร้าง API Code

  1. ไปด้านบนตรงช่อง เเล้วเสิร์ทคำว่า “Geocoding API”

2. จากนั้นก็กด Enable ⇒ Link (สำหรับแก้ไขปัญหากรณีที่ยัง API ไม่ได้)

3. จากนั้นเราจะไปสร้าง API กัน ไปที่เมนูเสิร์ทอีกครั้ง แล้วเลือก “Enabled API & services”

4. และไปที่ “Credentials” และกด “Create Credentials”

5. และเลือก API Key

*** และระบบ ก็จะ Generate API มาให้ แต่ว่า จะยังไม่สามารถใช้งาน API ได้ ต้องทำการ Edit เพื่อไปแก้ไข “Application restrictions” ก่อน และ 1 API จะสามารถใช้งานได้แค่ Application เดียวเท่านั้น ***

ซึ่งในส่วนนนี้ เราจะใช้กับ “IP addresses”

🚨 แต่ว่า … จะต้องใช้ IP Address จากไหนล่ะ มา ADD เข้าไปล่ะ ??

😏 หลังจากที่ลองผิดลองถูกมานาน ก็พบว่า หากจะใช้ Colab ในการดึง เราก็ต้องใช้ IP Address ของ Colab ดึง! ฮ่า (ฉันงมนานมากนะ เอาจริงๆ 🤣 ตอนแรกไปใช้ IP เครื่อง ก็ว่าทำไม API ใน Colab REQUEST_DENIED ตลอด)

การหา IP Address บน Colab

  1. มาต่อกันที่ใน Colab ⇒ https://colab.research.google.com/ กดเข้าลิ้งค์และสร้าง “New notebook” ได้เลย

2. จากนั้น ใช้โค้ตต่อไปนี้ เพื่อ RUN เรียกเลข IP Address ของ Colab’s Public IP Address ออกมา

import requests

# Fetch the public IP address
response = requests.get("https://api.ipify.org?format=json")

# Print the IP address
if response.status_code == 200:
    print("Colab's Public IP Address:", response.json()["ip"])
else:
    print("Failed to retrieve IP address")

3. เมื่อได้ เลขที่ IP Address เเล้ว ก็กลับมาที่ Google API เพื่อนำ IP Address ไป Add เข้า **บอกก่อนว่า IP Address ของแต่ละเครื่องที่เข้า Colab ก็จะไม่เหมือนกันนะ* ดังนั้นถ้าเปลี่ยนเครื่อง RUN ต้องดึง IP Address ใหม่ด้วย**

จากนั้นกด “SAVE” ระบบ จะเด้งกลับมาที่หน้า “Credentials” อัตโนมัติ

แต่นเต๊นนน 😎 จะเห็น icon เครื่องหมายถูก หน้า API ของเรา เป็นเครื่องการันตีว่า API ของเราสามารถใช้งานได้เเล้ว!

การทำ API บน Colab

ต่อมาเป็นขั้นตอนของการดึงเเล้วค่ะทู๊กคนน
(แค่ทำเส้น API ก็ 9 ข้อเเล้ว 🤣)

…..ก่อนจะทำบน Data จริง ขอทดสอบก่อนว่า ดึงข้อมูลอะไรออกมากันแน่นะวิ 🤨 โค้ตที่ใช้ทดสอบคือ **(ก่อน RUN ใช้งานจริง เอา API Key ของตัวเองมาใส่ใน ‘YOUR-GOOGLE-API’ นะ โดยที่ API ที่เป็น String ต้องอยู่ในเครื่องหมาย ‘ ’ (SINGLE QUOTATION MARK) หรือบ้านๆเราเรียกว่าโควท 🤣 **

# Define the API URL and API key
GOOGLE_API_KEY = 'YOUR-GOOGLE-API'  # Replace with your actual API key
lat, lon = 14.84238, 101.11501  # Replace with your test coordinates

# Construct the API URL
url = f"https://maps.googleapis.com/maps/api/geocode/json?latlng={lat},{lon}&key={GOOGLE_API_KEY}"

# Send the GET request to the API
response = requests.get(url)

# Check if the API request was successful (status code 200)
if response.status_code == 200:
    print("API request successful!")

    # Parse the JSON response
    data = response.json()

    # Check if 'status' is 'OK'
    if data.get('status') == 'OK':
        print("Geocoding successful. Data received:")
        print(data)  # Print the raw response data
    else:
        print(f"API request successful, but status: {data.get('status')}")
else:
    print(f"API request failed with status code: {response.status_code}")
    print(f"Error message: {response.text}")

ถ้า API สำเร็จ จะได้ Result ดังนี้ ซึ่ง Data received ที่ได้ จะเป็น JSON

😮 ข้อมูล ตำบล อำเภอ จังหวัด มีทั้งที่อยู่ชื่อเต็ม เป็นภาษาไทยและภาษาอังกฤษ เลือกได้ตามความต้องการ

แต่ของฉันจะ เลือกเป็น ตำบล อำเภอ และจังหวัด ภาษาไทยจ้า (company use thai base😆)

ใช้โค้ตดังนี้ 👉

(ที่ต้องตั้ง API rate limit เพราะ limitation ของ Geocoding API ได้ไม่เกิน 3000 queries per minutes เลยจำกัดป้องกันไว้ก่อน 😂 แต่จะ run ช้านิสนึง ใครอยาก optimize ลุยได้เลอนา …)

import pandas as pd
import requests
import logging
from time import sleep

# Enable logging
logging.basicConfig(level=logging.INFO)

# Mockup data
mockup_data = customer_Lat_long.copy()[['Latitude','Longitude']]
mockup_df = pd.DataFrame(mockup_data)

# Google Geocoding API Key
GOOGLE_API_KEY = 'YOUR-GOOGLE-API'  # Replace with your actual API key

# API rate limit settings
MAX_REQUESTS_PER_MINUTE = 3000
REQUEST_DELAY = 60 / MAX_REQUESTS_PER_MINUTE  # Delay per request

# Function to reverse geocode
def reverse_geocode(lat, lon):
    """
    Convert latitude and longitude into Sub-District (ตำบล), District (อำเภอ), and Province (จังหวัด).
    """
    try:
        # Make API request with language parameter set to Thai
        url = f"https://maps.googleapis.com/maps/api/geocode/json?latlng={lat},{lon}&language=th&key={GOOGLE_API_KEY}"
        response = requests.get(url)
        data = response.json()

        if data['status'] == 'OK':
            sub_district, district, province = 'Unknown', 'Unknown', 'Unknown'

            # Extract address components
            for component in data['results'][0].get('address_components', []):
                if 'locality' in component['types']:  # ตำบล
                    sub_district = component['long_name']
                elif 'administrative_area_level_2' in component['types']:  # อำเภอ
                    district = component['long_name']
                elif 'administrative_area_level_1' in component['types']:  # จังหวัด
                    province = component['long_name']

            return {"Sub-District": sub_district, "District": district, "Province": province}
        else:
            logging.warning(f"No results for coordinates ({lat}, {lon}): {data['status']}")
            return {"Sub-District": "Unknown", "District": "Unknown", "Province": "Unknown"}

    except Exception as e:
        logging.error(f"Error during geocoding for ({lat}, {lon}): {e}")
        return {"Sub-District": "Unknown", "District": "Unknown", "Province": "Unknown"}

# Perform geocoding
results = []
for _, row in mockup_df.iterrows():
    lat, lon = row['Latitude'], row['Longitude']
    result = reverse_geocode(lat, lon)
    results.append(result)
    sleep(REQUEST_DELAY)  # Respect API rate limit

# Combine results with original data
result_df = pd.concat([mockup_df, pd.DataFrame(results)], axis=1)

# Display the result
result_df

ผลลัพธ์ที่ได้

จะเห็นว่า มีบาง latitude และ Longtitude UNKNOWN_ERROR แต่ถือว่าน้อยมาก สามารถช่วยลดงานในการไปหา Maual เองได้เยอะเลยยย … 🎉🎉⇒ Final Code: Link

ปล. ถึงจะบอกว่าใช้ฟรีก็เถอะ 🥲 แต่ถ้ายิงเยอะเกินไป เจ้าตัว Geocoding API ก็ค่าใช้จ่ายสูงใช่เล่นเลยนะ

ขอแปะ Cost คร่าวๆ ไว้ … 👉 Link

อ่ะเช้านี้ บิลมาเเล้วจร้าาาา 😂

อันนี้ยังไม่ “Discount free tiers” นะ

ถ้าถามว่ายิงไปกี่ครั้ง (150,000 กว่าครั้งเองงง 🥹)

จบเเล้วจ้า.. 🙂

ใส่ความเห็น