שיטות מומלצות לשימוש ב-Street View Static API

ממשקי ה-HTTP של Google Maps Platform Static Web APIs יוצרים תמונות להטמעה ישירות בדף האינטרנט.

שירותי האינטרנט של Google Maps Platform הם אוסף של ממשקי HTTP שמספקים נתונים גיאוגרפיים לאפליקציות המפות שלכם.

במדריך הזה מתוארות כמה שיטות נפוצות שימושיות להגדרת בקשות לשירותי תמונות ושירותי אינטרנט ולעיבוד תשובות של שירותים. מידע נוסף על Street View Static API זמין במדריך למפתחים.

‫Street View Static API פועל כמו Web API סטטי, ושירות המטא-נתונים פועל כמו שירות אינטרנט. מידע נוסף על שירות המטא-נתונים זמין במאמר מטא-נתונים של תמונות Street View.

מה זה Static Web API?

ממשקי ה-API הסטטיים של Google Maps Platform מאפשרים להטמיע תמונה של מפות Google בדף אינטרנט בלי להשתמש ב-JavaScript או בטעינה דינמית של דפים. ממשקי ה-API הסטטיים לאינטרנט יוצרים תמונה על סמך פרמטרים של כתובת URL שנשלחים באמצעות בקשת HTTPS רגילה.

בקשת API אופיינית ל-Street View Static נראית כך:

  https://www.googleapis.com/streetview/z/x/y?parameters

מהו שירות אינטרנט?

שירותי האינטרנט של Google Maps Platform הם ממשק לשליחת בקשות לנתוני Maps API משירותים חיצוניים ולשימוש בנתונים באפליקציות של מפות Google. השירותים האלה מיועדים לשימוש בשילוב עם מפה, בהתאם להגבלות הרישיון שמופיעות בתנאים ובהגבלות של Google Maps Platform.

שירותי האינטרנט של ממשקי Maps APIs משתמשים בבקשות HTTP או HTTPS לכתובות URL ספציפיות, ומעבירים פרמטרים של כתובות URL או נתוני POST בפורמט JSON כארגומנטים לשירותים. בדרך כלל, השירותים האלה מחזירים נתונים בגוף התגובה בפורמט JSON לצורך ניתוח או עיבוד על ידי האפליקציה.

בקשה למטא-נתונים של Street View Static API היא מהצורה הבאה:

‫
https://maps.googleapis.com/maps/api/streetview/parameters

גישה ל-SSL ול-TLS

חובה להשתמש ב-HTTPS בכל הבקשות ל-Google Maps Platform שמשתמשות במפתחות API או מכילות נתוני משתמשים. יכול להיות שבקשות שמועברות דרך HTTP ומכילות מידע אישי רגיש יידחו.

יצירת כתובת URL תקינה

יכול להיות שאתם חושבים שכתובת URL 'תקינה' היא דבר ברור מאליו, אבל זה לא בדיוק המצב. לדוגמה, כתובת URL שמוזנת בסרגל הכתובות בדפדפן עשויה להכיל תווים מיוחדים (למשל, "上海+中國"). הדפדפן צריך לתרגם את התווים האלה באופן פנימי לקידוד אחר לפני השידור. באופן דומה, כל קוד שמייצר או מקבל קלט UTF-8 עשוי להתייחס לכתובות URL עם תווים בקידוד UTF-8 כאל כתובות 'תקינות', אבל הוא גם יצטרך לתרגם את התווים האלה לפני שהוא שולח אותם לשרת אינטרנט. התהליך הזה נקרא קידוד כתובות URL או קידוד באחוזים.

תווים מיוחדים

אנחנו צריכים לתרגם תווים מיוחדים כי כל כתובות ה-URL צריכות להתאים לתחביר שמוגדר במפרט של מזהה משאב אחיד (URI). בפועל, המשמעות היא שכתובות URL חייבות להכיל רק קבוצת משנה מיוחדת של תווים מסוג ASCII: הסמלים האלפאנומריים המוכרים, וכמה תווים שמורים לשימוש כתווי בקרה בכתובות URL. בטבלה הבאה מפורטים התווים האלה:

סיכום של תווים תקינים בכתובת URL
הגדרהתוויםשימוש בכתובות URL
אלפאנומרי a b c d e f g h i j k l m n o p q r s t u v w x y z A B C D E F G H I J K L M N O P Q R S T U V W X Y Z 0 1 2 3 4 5 6 7 8 9 מחרוזות טקסט, שימוש בסכימה (http), יציאה (8080) וכו'.
לא שמור ‪- _ . ~ מחרוזות טקסט
בוצעה הזמנה ! * ' ( ) ; : @ & = + $ , / ? ‫% # [ ] תווי בקרה או מחרוזות טקסט

כשיוצרים כתובת URL תקינה, צריך לוודא שהיא מכילה רק את התווים שמוצגים בטבלה. התאמה של כתובת URL לשימוש בסט התווים הזה בדרך כלל מובילה לשתי בעיות, אחת של השמטה ואחת של החלפה:

  • יש תווים שרוצים לטפל בהם שלא נכללים בקבוצה שלמעלה. לדוגמה, תווים בשפות זרות כמו 上海+中國 צריכים להיות מקודדים באמצעות התווים שלמעלה. לפי מוסכמה נפוצה, רווחים (שאסור להשתמש בהם בכתובות URL) מיוצגים לעיתים קרובות גם באמצעות התו '+'.
  • התווים האלה קיימים בסט שלמעלה כתווים שמורים, אבל צריך להשתמש בהם באופן מילולי. לדוגמה, התו ? משמש בכתובות URL כדי לציין את תחילת מחרוזת השאילתה. אם רוצים להשתמש במחרוזת '? and the Mysterions', צריך לקודד את התו '?'.

כל התווים שמיועדים לקידוד URL מקודדים באמצעות התו '%' וערך הקסדצימלי בן שני התווים שמתאים לתווים בקידוד UTF-8. לדוגמה, 上海+中國 ב-UTF-8 יותאם לקידודי התווים שמתאימים לכתובות URL באופן הבא: %E4%B8%8A%E6%B5%B7%2B%E4%B8%AD%E5%9C%8B. המחרוזת ? and the Mysterians תעבור קידוד כתובות URL כ-%3F+and+the+Mysterians או כ-%3F%20and%20the%20Mysterians.

תווים נפוצים שצריך לקודד

אלה כמה תווים נפוצים שצריך לקודד:

תו לא בטוח ערך מקודד
רווח %20
" %22
< %3C
> %3E
# %23
% %25
| %7C

לפעמים קשה להמיר כתובת URL שמתקבלת מקלט של משתמשים. לדוגמה, משתמש יכול להזין כתובת כ-"5th&Main St." באופן כללי, צריך ליצור את כתובת ה-URL מהחלקים שלה, ולהתייחס לכל קלט של משתמשים כאל תווים מילוליים.

בנוסף, כתובות URL מוגבלות ל-16,384 תווים בכל שירותי האינטרנט של Google Maps Platform ובממשקי API סטטיים לאינטרנט. ברוב השירותים, לא תגיעו למגבלת התווים הזו. עם זאת, חשוב לשים לב שלחלק מהשירותים יש כמה פרמטרים שיכולים לגרום לכתובות URL ארוכות.

שימוש מנומס ב-Google APIs

לקוחות API עם עיצוב לקוי עלולים להעמיס עומסים כבדים על האינטרנט ועל השרתים. בקטע הזה מפורטות שיטות מומלצות לשימוש בלקוחות API. השיטות המומלצות האלה יעזרו לכם למנוע חסימה של האפליקציה בגלל ניצול לרעה לא מכוון של ממשקי ה-API.

השהיה מעריכית לפני ניסיון חוזר (exponential backoff)

במקרים נדירים, יכול להיות שמשהו ישתבש בבקשה שלכם. יכול להיות שתקבלו קוד תגובת HTTP מסוג 4xx או 5xx, או שהחיבור ל-TCP ייכשל איפשהו בין הלקוח לשרת של Google. לעתים קרובות כדאי לנסות שוב את הבקשה, כי יכול להיות שהבקשה הבאה תצליח גם אם המקורית נכשלה. עם זאת, חשוב לא לשלוח בקשות לשרתים של Google שוב ושוב. התנהגות הלולאה הזו עלולה ליצור עומס יתר ברשת שבין הלקוח לבין Google, ולגרום לבעיות עבור גורמים רבים.

גישה טובה יותר היא לנסות שוב עם עיכובים הולכים וגדלים בין הניסיונות. בדרך כלל, העיכוב גדל בפקטור כפלי בכל ניסיון, גישה שנקראת השהיה מעריכית לפני ניסיון חוזר (exponential backoff).

לדוגמה, נניח שיש אפליקציה ששולחת את הבקשה הזו ל-Time Zone API:

https://maps.googleapis.com/maps/api/timezone/json?location=39.6034810,-119.6822510&timestamp=1331161200&key=YOUR_API_KEY

בדוגמה הבאה של Python אפשר לראות איך לשלוח את הבקשה עם השהיה מעריכית לפני ניסיון חוזר (exponential backoff):

import json
import time
import urllib.error
import urllib.parse
import urllib.request

# The maps_key defined in the following code isn't a valid Google Maps API key.
# You need to get your own API key.
# See https://developers.google.com/maps/documentation/timezone/get-api-key
API_KEY = "YOUR_KEY_HERE"
TIMEZONE_BASE_URL = "https://maps.googleapis.com/maps/api/timezone/json"


def timezone(lat, lng, timestamp):

    # Join the parts of the URL together into one string.
    params = urllib.parse.urlencode(
        {"location": f"{lat},{lng}", "timestamp": timestamp, "key": API_KEY,}
    )
    url = f"{TIMEZONE_BASE_URL}?{params}"

    current_delay = 0.1  # Set the initial retry delay to 100ms.
    max_delay = 5  # Set the maximum retry delay to 5 seconds.

    while True:
        try:
            # Get the API response.
            response = urllib.request.urlopen(url)
        except urllib.error.URLError:
            pass  # Fall through to the retry loop.
        else:
            # If the request didn't produce an IOError, parse the result.
            result = json.load(response)

            if result["status"] == "OK":
                return result["timeZoneId"]
            elif result["status"] != "UNKNOWN_ERROR":
                # Many API errors can't be fixed by a retry, such as
                # INVALID_REQUEST or ZERO_RESULTS. Don't retry these requests.
                raise Exception(result["error_message"])

        if current_delay > max_delay:
            raise Exception("Too many retry attempts.")

        print("Waiting", current_delay, "seconds before retrying.")

        time.sleep(current_delay)
        current_delay *= 2  # Increase the delay on each retry.


if __name__ == "__main__":
    tz = timezone(39.6034810, -119.6822510, 1331161200)
    print(f"Timezone: {tz}")

חשוב לוודא שאין קוד לניסיון חוזר גבוה יותר בשרשרת הקריאות של האפליקציה שמוביל לבקשות חוזרות בזו אחר זו.

בקשות מסונכרנות

מספר גדול של בקשות מסונכרנות ל-Google APIs יכול להיראות כמו מתקפת מניעת שירות מבוזרת (DDoS) על התשתית של Google, ולכן המערכת תתייחס אליהן בהתאם. כדי להימנע מהבעיה הזו, צריך לוודא שבקשות ה-API לא מסונכרנות בין לקוחות.

לדוגמה, אפליקציה שמציגה את השעה באזור הזמן הנוכחי. האפליקציה הזו כנראה מגדירה התראה במערכת ההפעלה של הלקוח כדי להפעיל אותה בתחילת הדקה, כך שהזמן שמוצג יוכל להתעדכן. אל תבצעו קריאות ל-API באפליקציה כחלק מהעיבוד שמשויך לאזעקה הזו.

ביצוע קריאות ל-API בתגובה לאזעקה קבועה הוא דבר לא טוב, כי הוא גורם לכך שהקריאות ל-API מסונכרנות לתחילת הדקה, גם בין מכשירים שונים, במקום להתפלג באופן שווה לאורך זמן. אפליקציה עם עיצוב לקוי שמבצעת את הפעולה הזו יוצרת קפיצה בעומס התנועה לרמה שהיא פי 60 מהרמה הרגילה בתחילת כל דקה.

במקום זאת, אפשר לתכנן את האפליקציה כך שתהיה בה התראה שנייה שמוגדרת לשעה שנבחרה באופן אקראי. כשהאזעקה השנייה מופעלת, האפליקציה קוראת לכל ממשקי ה-API שהיא צריכה ושומרת את התוצאות. כשהאפליקציה מעדכנת את התצוגה שלה בתחילת הדקה, היא משתמשת בתוצאות שנשמרו קודם במקום לקרוא שוב ל-API. בגישה הזו, הקריאות ל-API מתבצעות בהפרשים קבועים לאורך זמן. בנוסף, הקריאות ל-API לא מעכבות את העיבוד כשהתצוגה מתעדכנת.

בנוסף לתחילת הדקה, לא מומלץ לטרגט זמני סנכרון נפוצים אחרים, כמו תחילת השעה ותחילת כל יום בחצות.

עיבוד התשובות

מכיוון שלא מובטח הפורמט המדויק של תשובות נפרדות לבקשה משירות אינטרנט – יכול להיות שחלק מהרכיבים חסרים או מופיעים בכמה מקומות – אל תניחו שהפורמט שמוחזר עבור תשובה מסוימת זהה לפורמט של שאילתות אחרות. במקום זאת, מעבדים את התגובה ובוחרים ערכים מתאימים באמצעות ביטויים.

בקטע הזה נסביר איך לחלץ את הערכים האלה באופן דינמי מתגובות של שירותי אינטרנט.

שירותי האינטרנט של מפות Google מספקים תשובות מובנות, אבל לא ידידותיות למשתמש. כשמבצעים שאילתה, בדרך כלל רוצים לחלץ כמה ערכים ספציפיים ולא להציג קבוצת נתונים. בדרך כלל, מנתחים את התשובות משירות האינטרנט ומחלצים רק את הערכים שמעניינים אתכם.

סכימת הניתוח שבה משתמשים תלויה בשאלה אם מחזירים פלט ב-JSON. תגובות JSON, שכבר נמצאות בפורמט של אובייקטים ב-JavaScript, יכולות לעבור עיבוד בתוך JavaScript עצמו בצד הלקוח.