Tìm kiếm dọc theo tuyến đường bằng API địa điểm

Tài liệu này mô tả cách tìm khách sạn, nhà hàng hoặc trạm xăng dọc theo một tuyến đường đã lên kế hoạch. Bạn sẽ tìm hiểu cách sử dụng Routes API để lấy một chuỗi đường nhiều đoạn và sử dụng chuỗi đó với yêu cầu Places API Tìm kiếm dọc theo tuyến đường (SAR). Bạn cũng sẽ tìm hiểu cách đạt được kết quả tốt nhất bằng cách đặt điểm bắt đầu tìm kiếm dọc theo tuyến đường, ví dụ: 2 giờ sau khi bắt đầu chuyến đi.

Routes API

Để tìm kiếm các địa điểm dọc theo tuyến đường, chúng ta sẽ sử dụng Routes API. Dữ liệu tuyến đường trong phản hồi của Routes API là một chuỗi gồm các toạ độ LatLong từ điểm bắt đầu đến điểm đến. Dữ liệu tuyến đường chứa các đoạn đường và bước đi theo mạng lưới đường bộ.

Các tuyến đường cũng được trả về dưới dạng đường đa tuyến được mã hoá mà bạn truyền dưới dạng tham số đầu vào cho yêu cầu SAR. Mã hoá nhiều đường là một thuật toán nén mất dữ liệu cho phép bạn lưu trữ một chuỗi các toạ độ dưới dạng một chuỗi duy nhất. Bạn không bắt buộc phải lấy đường nhiều đoạn từ Routes API. Bạn có thể tự tạo dữ liệu nhưng cho mục đích của ví dụ này, Routes API là một cách nhanh chóng và chắc chắn để lấy dữ liệu cần thiết.

Trong hướng dẫn này, chúng ta sẽ sử dụng một tuyến đường từ London (-37.8167,144.9619) đến Manchester (-37.8155, 144.9663)

Tuyến đường từ London đến Manchester

Tuyến đường trong ví dụ: London đến Manchester

Bước 1: Lấy một tuyến đường từ Routes API

Để nhận được một tuyến đường từ Routes API, bạn sẽ cần cung cấp thông tin sau:

  • Vị trí điểm xuất phát và điểm đến
  • Phương tiện giao thông (lái xe, đi bộ, v.v.)
  • Mọi điểm đánh dấu (không bắt buộc)
  • Mọi lựa chọn ưu tiên (tránh trạm thu phí, tránh đường cao tốc, v.v.)
  • Lựa chọn ưu tiên về định tuyến dựa trên lưu lượng truy cập sẽ cung cấp cho bạn thông tin ước tính chính xác nhất, nhưng đây là một hoạt động đòi hỏi nhiều tính toán và do đó làm tăng độ trễ của phản hồi.
{"origin":{
    "location": {
        "latLng":{
            "latitude":  -37.8167,
            "longitude": 144.9619
        }
    }
},
"destination":{
    "location": {
        "latLng":{
            "latitude":-37.8155,
            "longitude": 144.9663
        }
    }
},
"routingPreference":"TRAFFIC_AWARE",
"travelMode":"DRIVE"
}

Khi thực hiện lệnh gọi, hãy nhớ thêm trường "encodedPolyline" vào mặt nạ trường tiêu đề.

headers = {
    "Content-Type": "application/json",
    "X-Goog-FieldMask": "routes.distanceMeters,routes.duration,routes.legs,routes.polyline.encodedPolyline"
}

Tài liệu đầy đủ kèm theo ví dụ về cách lấy một tuyến đườnglấy nhiều đường trên tuyến đường.

Sau khi bạn cung cấp thông tin này trong yêu cầu, Routes API sẽ trả về một đối tượng tuyến đường. Đối tượng tuyến đường sẽ chứa những thông tin sau:

  • Tổng quãng đường của tuyến đường
  • Tổng thời gian di chuyển của tuyến đường
  • Các đoạn đường và bước đi của tuyến đường
  • Hình nhiều đường được mã hoá của tuyến đường, chặng và bước.
{
  "routes": [
    {
      "legs": [
        {
          "distanceMeters": 321799,
          "duration": "15401s",
          "staticDuration": "14518s",
          "polyline": {
            "encodedPolyline": "y_kyH`_XOr@q@xKGnBBZ|AlGPj@Y^k@^MEqAfAQLK?eI … <rest of content removed for readability>"
          },
          "startLocation": {
            "latLng": {
              "latitude": 51.507334500000006,
              "longitude": -0.1280107
            }
          },
          "endLocation": {
            "latLng": {
              "latitude": 53.4808513,
              "longitude": -2.2425864
            }
          },
          "steps": [
            {
              "distanceMeters": 320,
              "staticDuration": "82s",
              "polyline": {
                "encodedPolyline": "y_kyH`_XOr@q@xKGnBBZ|AlG"
              },
              "startLocation": {
                "latLng": {
                  "latitude": 51.507334500000006,
                  "longitude": -0.1280107
                }
              },
              "endLocation": {
                "latLng": {
                  "latitude": 51.507207,
                  "longitude": -0.1323681
                }
              },
              "navigationInstruction": {
                "maneuver": "DEPART",
                "instructions": "Head northwest on Trafalgar Sq/A4 toward Spring Gardens\nContinue to follow A4\nLeaving toll zone\nEntering toll zone\nLeaving toll zone in 210m at Haymarket"
              },
              "localizedValues": {
                "distance": {
                  "text": "0.3 km"
                },
                "staticDuration": {
                  "text": "1 min"
                }
              },
# rest of the response removed for readability

Bước 2: Yêu cầu Tìm kiếm dọc theo tuyến đường

Tính năng Tìm kiếm bằng văn bản của Places API có một yêu cầu Tìm kiếm dọc theo tuyến đường cho phép bạn tìm kiếm địa điểm dọc theo một tuyến đường. Để thực hiện yêu cầu Tìm kiếm dọc theo tuyến đường, bạn cần cung cấp tối thiểu những thông tin sau:

  • Mặt nạ trường cho biết những trường nào được trả về trong phản hồi
  • Khoá API hợp lệ cho API được bật trong Google Cloud Console
  • Chuỗi văn bản tìm kiếm cho biết những địa điểm bạn đang tìm, ví dụ: "nhà hàng chay cay"
  • Đường nhiều đoạn được mã hoá của tuyến đường, được truy xuất từ lệnh gọi Routes API trước đó
  • URL cho điểm cuối Places Text Search API
import requests

url = 'https://places.googleapis.com/v1/places:searchText'
api_key = 'YOUR_API_KEY'  # Replace with your actual API key
route_polyline = 'YOUR_ROUTE_POLYLINE'  # Replace with your encoded route polyline

headers = {
    'Content-Type': 'application/json',
    'X-Goog-Api-Key': api_key,
    'X-Goog-FieldMask': 'places.displayName,places.formattedAddress,places.priceLevel'
}

data = {
    "textQuery":
 "Spicy Vegetarian Food",
    "searchAlongRouteParameters": {
        "polyline": {
            "encodedPolyline": route_polyline
        }
    }
}

response = requests.post(url, headers=headers, json=data)

Ví dụ về dữ liệu yêu cầu

Yêu cầu Tìm kiếm dọc theo tuyến đường sẽ trả về danh sách các địa điểm nằm dọc theo tuyến đường. Dưới đây là một phần nhỏ của dữ liệu mẫu. Độ dài của phản hồi có thể bị giới hạn bằng cách đặt tham số số lượng kết quả tối đa và việc thêm nhiều trường hơn tất nhiên sẽ làm tăng lượng dữ liệu nhận được. Để biết thêm thông tin chi tiết về phản hồi của Places API, hãy xem tài liệu.

{
  "places": [
    {
      "formattedAddress": "33 Haymarket, London SW1Y 4HA, UK",
      "displayName": {
        "text": "xxx",
        "languageCode": "en"
      }
    },
    {
      "formattedAddress": "224 Piccadilly, London W1J 9HP, UK",
      "priceLevel": "PRICE_LEVEL_MODERATE",
      "displayName": {
        "text": "yyy",
        "languageCode": "en"
      }
    },
    {
      "formattedAddress": "63 Neal St, London WC2H 9PJ, UK",
      "displayName": {
        "text": "zzz",
        "languageCode": "en"
      }
    },

Ví dụ về dữ liệu phản hồi

Tóm tắt về tuyến đường và thời gian đi đường vòng

Việc tìm thấy các địa điểm là rất tốt, nhưng sẽ hữu ích hơn nếu bạn thêm thông tin về thời gian cần thiết để đến những địa điểm này. SAR trong Places API Text Search cũng có thể trả về một trường routing summaries (tóm tắt thông tin định tuyến) chứa cả thời lượng và khoảng cách di chuyển. Trường dữ liệu tóm tắt về việc định tuyến là một phần tử con của gốc phản hồi, vì vậy, bạn không được thêm tiền tố "places." vào mặt nạ trường.

'X-Goog-FieldMask': 'places.displayName,places.formattedAddress,places.priceLevel,routingSummaries'

Để nhận được thông tin tóm tắt, bạn cũng phải cung cấp tham số vị trí xuất phát cho cụm từ tìm kiếm được dùng để tính toán.

"routingParameters": {
      "origin": {
        "latitude":  -37.8167,
        "longitude": 144.9619
      }
    }

Khi bạn nhận được phản hồi, phản hồi đó sẽ có một phần mới có thông tin tóm tắt về đường đi chứa các đoạn đường có thời lượng và khoảng cách tính bằng mét.

"routingSummaries": [
    {
      "legs": [
        {
          "duration": "662s",
          "distanceMeters": 3093
        }
      ]
    },

Tiếp theo, chúng ta sẽ xem cách bạn có thể xác định vị trí bắt đầu tìm kiếm dọc theo tuyến đường.

Bước 3: Lấy vị trí cách 2 giờ dọc theo tuyến đường

Hãy cân nhắc một trường hợp sử dụng thông thường, trong đó người lái xe muốn tìm nhà hàng không phải ở điểm bắt đầu của tuyến đường mà ở xa hơn trên đường. Trong ví dụ của chúng tôi, chuyến đi từ London đến Manchester mất khoảng 4 giờ. Người lái xe muốn tìm một nhà hàng cách đó 2 giờ lái xe trên tuyến đường. Yêu cầu này cho chúng ta biết thời lượng là 120 phút * 60 giây = 7200 giây.

Trong phản hồi Routes API, chúng ta có thời lượng của từng đoạn đường trong tuyến đường và từng bước của một đoạn đường. Hãy nhớ thêm trường "legs" vào mặt nạ trường trong yêu cầu của bạn. Lặp lại các chặng và bước cho đến khi thời lượng tích luỹ đạt đến giới hạn 2 giờ hoặc 7200 giây. Sau đó, chúng tôi đã tìm thấy chặng và bước cần đặt làm điểm bắt đầu của yêu cầu SAR

Để đẩy nhanh tiến độ công việc, bạn có thể dùng thử thư viện nhiều đường cho Python. Bạn có thể dùng phương thức này để lấy toạ độ từ trường dữ liệu "polyline.endodedPolyline".

Chạy các lệnh sau trong cửa sổ dòng lệnh của môi trường.

> pip install polyline
import requests
import polyline

# We've covered getting a Routes API response earlier,
data = response.json()

  # Extract the first route and its encoded polyline
  route = data["routes"][0]
  polyline_points = polyline.decode(route["polyline"]["encodedPolyline"])

  # Calculate total duration of the route in seconds
  total_duration_seconds = route["duration"]

  # Calculate the desired time offset in seconds, 2h = 120 minutes * 60
  desired_time_offset_seconds = time_offset_minutes * 60

  # Iterate through the legs and steps to find the point at the desired time offset
  elapsed_time_seconds = 0
  for leg in route["legs"]:
      for step in leg["steps"]:
          step_duration_seconds = step["staticDuration"]

          # Check if the desired time offset falls within this step, remove last "s" from string and convert to int
          second_value = int(step_duration_seconds[:-1])
          if elapsed_time_seconds + second_value >= desired_time_offset_seconds:
              # Interpolate to find the exact point within the step
              fraction_of_step = (desired_time_offset_seconds - elapsed_time_seconds) / second_value
              step_polyline_points = polyline.decode(step["polyline"]["encodedPolyline"])
              index = int(len(step_polyline_points) * fraction_of_step)
              return step_polyline_points[index]

          elapsed_time_seconds += second_value

  # If the point is not found (e.g., time offset exceeds route duration)
  return None

Giờ đây, chúng ta đã tìm thấy vị trí trên tuyến đường cách điểm bắt đầu 2 giờ lái xe, chúng ta có thể sử dụng vị trí đó trong yêu cầu. Bạn chỉ cần thêm vĩ độ và kinh độ vào tham số "origin". Tham số này là một phần của tham số "routingParameters". Bạn nên dùng trường dữ liệu "routingSummaries" mà chúng ta đã đề cập trước đó. Bạn cũng có thể thêm các thông số khác như chế độ di chuyển và chỉ dẫn để tránh đường có thu phí nếu muốn.


"routingParameters": {
    "origin": {
      "latitude": xx.xxxx,
      "longitude": yy.yyyy
    },
    "travelMode":"DRIVE",
    "routeModifiers": {
      "avoidTolls": true
    }
  }

Đường đi có kết quả tìm kiếm

Kết quả ví dụ (đã thêm biểu tượng ô tô để cho biết nguồn gốc của lượt tìm kiếm).

Như bạn có thể thấy trong hình ảnh, API trả về những địa điểm có xu hướng nằm ở cuối tuyến đường, kết quả bắt đầu từ khoảng giữa chuyến đi. Tính năng tìm kiếm này vẫn được hỗ trợ bởi cùng một dữ liệu của Google Maps Platform, trong đó có tính đến mức độ liên quan của địa điểm và khoảng cách, cùng nhiều yếu tố khác.

Lời kết

Trong hướng dẫn này, chúng ta đã tìm hiểu cách kết hợp 2 API của Google Maps Platform (Routes và Places) để lên kế hoạch cho một chuyến đi và tìm địa điểm ăn uống sau 2 giờ di chuyển. Các bước cần thực hiện là lấy một đường nhiều đoạn được mã hoá chứa toạ độ vĩ độ và kinh độ cho từng bước trên đường đi, đồng thời đặt nguồn yêu cầu Tìm kiếm dọc theo tuyến đường để nhận được kết quả tốt nhất.

Tính năng này bổ sung một công cụ mới mạnh mẽ cho tính năng tìm kiếm bằng văn bản và tìm kiếm lân cận hiện có trong Places API. Bước tiếp theo hợp lý sẽ là thêm dịch vụ vị trí để bạn có thể sử dụng vị trí của người lái xe làm điểm bắt đầu để tìm vị trí xuất phát tối ưu cho việc tìm kiếm. Ngoài ra, tính năng này sẽ hoạt động hoàn hảo cùng với một trợ lý giọng nói trong ô tô mà bạn sẽ nói ra các lựa chọn ăn uống mà mình muốn.

Các bước tiếp theo

Tài liệu đọc thêm được đề xuất:

Cộng tác viên

Google duy trì tài liệu này. Người đóng góp sau đây là tác giả gốc của bài viết này.

Tác giả chính: Mikko Toivanen | Kỹ sư giải pháp của Nền tảng Google Maps