سرویسهای وب «پلاتفرم Google Maps» مجموعهای از میاناهای HTTP به سرویسهای Google است که دادههای جغرافیایی را برای برنامههای نقشه شما ارائه میدهد.
این راهنما برخیاز روالهای رایج را که برای راهاندازی درخواستهای سرویس وب و پردازش پاسخهای سرویس مفید هستند شرح میدهد. برای دریافت مستندات کامل Time Zone API، به راهنمای توسعهدهنده مراجعه کنید.
سرویس وب چیست؟
خدمات وب «پلاتفرم Google Maps» میانایی برای درخواست دادههای Maps API از سرویسهای خارجی و استفاده از دادهها در برنامههای Maps شما است. این سرویسها طبق محدودیتهای پروانه در «شرایط خدمات پلاتفرم Google Maps» طراحی شدهاند تا همراه با نقشه استفاده شوند.
خدمات وب «میاناهای برنامهسازی کاربردی Maps» از درخواستهای HTTP(S) به نشانیهای وب خاص استفاده میکنند و پارامترهای نشانی وب و/یا دادههای POST با قالب JSON را بهعنوان آرگومان به سرویسها ارسال میکنند. بهطور کلی، این سرویسها دادهها را در بدنه پاسخ بهصورت JSON یا XML برای تجزیه و/یا پردازش توسط برنامه شما برمیگردانند.
درخواست معمول Time Zone API بهطورکلی بهشکل زیر است:
https://maps.googleapis.com/maps/api/timezone/output?parameters
که output نشاندهنده قالب پاسخ است (معمولاً
json یا xml).
توجه: همه برنامههای «میانای برنامهسازی کاربردی منطقه زمانی» به اصالتسنجی نیاز دارند. درباره اعتبارنامههای اصالتسنجی بیشتر بدانید.
دسترسی SSL/TLS
برای همه درخواستهای «پلاتفرم Google Maps» که از کلیدهای API استفاده میکنند یا حاوی دادههای کاربر هستند، HTTPS الزامی است. درخواستهایی که ازطریق HTTP ارسال میشوند و حاوی دادههای حساس هستند ممکن است رد شوند.
درحال ساختن نشانی وب معتبر
ممکن است فکر کنید که نشانی وب «معتبر» واضح است، اما
اینطور نیست. نشانی وبی که در نوار نشانی مرورگر وارد میشود، برای مثال، ممکن است نویسههای خاصی داشته باشد (مثلاً "上海+中國")؛ مرورگر باید قبلاز انتقال، این نویسهها را بهصورت داخلی به کدبندی دیگری ترجمه کند.
بههمین ترتیب، هر کدی که ورودی UTF-8 تولید یا دریافت میکند
ممکن است نشانیهای وب دارای نویسههای UTF-8 را «معتبر» درنظر بگیرد، اما همچنین باید
این نویسهها را قبلاز ارسال به سرور وب ترجمه کند.
این فرایند
کدبندی نشانی وب یا کدبندی درصدی نامیده میشود.
نویسههای خاص
باید نویسههای خاص را ترجمه کنیم زیرا همه نشانیهای وب باید با نحو مشخصشده در مشخصات شناسه منبع یکسان (URI) مطابقت داشته باشند. در عمل، این یعنی نشانیهای وب باید فقط شامل زیرمجموعه خاصی از نویسههای ASCII باشد: نمادهای آشنای الفبایی-عددی، و برخیاز نویسههای رزروشده برای استفاده بهعنوان نویسههای کنترلی در نشانیهای وب. این جدول این نویسهها را خلاصه میکند:
| بهصف | نویسهها | استفاده از نشانی وب |
|---|---|---|
| الفباعددی | 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)، و غیره. |
| رزرو نشده | - _ . ~ | رشتههای نوشتاری |
| رزروشده | ! * ' ( ) ; : @ & = + $ , / ? % # [ ] | نویسههای کنترلی و/یا رشتههای نوشتاری |
هنگام ساختن نشانی وب معتبر، باید مطمئن شوید که فقط حاوی نویسههای نشاندادهشده در جدول باشد. مطابقت دادن نشانی وب برای استفاده از این مجموعه نویسهها معمولاً به دو مشکل منجر میشود، یکی حذف و دیگری جایگزینی:
- نویسههایی که میخواهید مدیریت کنید خارج از مجموعه
بالا هستند. برای مثال، نویسههای زبانهای خارجی مانند
上海+中國باید بااستفاده از نویسههای بالا کدبندی شوند. طبق قراردادهای رایج، فاصلهها (که در نشانیهای وب مجاز نیستند) اغلب بااستفاده از نویسه بهعلاوه'+'نیز نشان داده میشوند. - نویسهها در مجموعه بالا بهعنوان نویسههای رزروشده وجود دارند،
اما باید بهصورت واقعی استفاده شوند.
برای مثال،
?در نشانیهای وب برای نشان دادن شروع رشته پُرسمان استفاده میشود؛ اگر میخواهید از رشته «؟ و Mysterions» استفاده کنید، باید نویسه'?'را کدبندی کنید.
همه نویسههایی که باید کدبندی URL شوند، بااستفاده از نویسه '%' و مقدار هگز دو نویسهای مربوط به نویسه UTF-8 آنها کدبندی میشوند. برای مثال،
上海+中國 در UTF-8 بهصورت
%E4%B8%8A%E6%B5%B7%2B%E4%B8%AD%E5%9C%8B کدبندی نشانی وب میشود. رشته ? and the Mysterians بهصورت
%3F+and+the+Mysterians یا %3F%20and%20the%20Mysterians کدبندی نشانی وب میشود.
نویسههای رایجی که نیاز به کدبندی دارند
برخیاز نویسههای رایج که باید کدبندی شوند عبارتاند از:
| نویسه ناامن | مقدار کدبندیشده |
|---|---|
| فاصله | %20 |
| » | %22 |
| < | %3C |
| > | %3E |
| # | %23 |
| ٪ | %25 |
| | | %7C |
تبدیل نشانی وبی که از درونداد کاربر دریافت میکنید گاهی اوقات دشوار است. برای مثال، کاربر ممکن است نشانی را بهصورت «5th&Main St.» وارد کند. بهطورکلی، باید نشانی وب خود را از بخشهای آن بسازید و هر ورودی کاربر را بهعنوان نویسههای تحتاللفظی درنظر بگیرید.
علاوهبراین، نشانیهای وب برای همه سرویسهای وب «پلاتفرم Google Maps» و «میاناهای برنامهسازی کاربردی وب» ایستا به ۱۶۳۸۴ نویسه محدود شده است. برای اکثر سرویسها، این حد نویسه بهندرت نزدیک میشود. بااینحال، توجه داشته باشید که برخیاز سرویسها چندین پارامتر دارند که ممکن است منجر به نشانیهای وب طولانی شود.
استفاده مؤدبانه از Google APIs
کاربران میانای برنامهسازی کاربردی که طراحی ضعیفی دارند میتوانند بار بیشتری از حد لازم را هم روی اینترنت و هم روی سرورهای Google قرار دهند. این بخش حاوی برخیاز روالهای مطلوب برای مشتریان میاناهای برنامهسازی کاربردی است. رعایت این روالهای مطلوب میتواند به شما کمک کند از مسدود شدن برنامهتان بهدلیل سوءاستفاده ناخواسته از میاناهای برنامهسازی کاربردی جلوگیری کنید.
پسگیری نمایی
در موارد نادر، ممکن است مشکلی در ارائه درخواست شما پیش بیاید؛ ممکن است کد پاسخ HTTP 4XX یا 5XX دریافت کنید، یا اتصال TCP ممکن است در جایی بین مشتری شما و سرور Google با مشکل مواجه شود. اغلب ارزش دارد که درخواست را دوباره امتحان کنید زیرا درخواست پیگیری ممکن است درحالیکه درخواست اصلی ناموفق بوده است موفق شود. بااینحال، مهم است که بهسادگی در یک حلقه تکراری درخواستهای مکرر به سرورهای Google ارسال نکنید. این رفتار حلقهای میتواند شبکه بین کارخواه شما و Google را بیشازحد بارگذاری کند و برای بسیاری از طرفین مشکل ایجاد کند.
رویکرد بهتر این است که با افزایش تأخیر بین تلاشها، دوباره امتحان کنید. معمولاً تأخیر با هر تلاش با یک عامل ضربی افزایش مییابد، رویکردی که بهعنوان عقبگرد نمایی شناخته میشود.
برای مثال، برنامهای را درنظر بگیرید که میخواهد این درخواست را به Time Zone API ارسال کند:
https://maps.googleapis.com/maps/api/timezone/json?location=39.6034810,-119.6822510×tamp=1331161200&key=YOUR_API_KEYمثال Python زیر نشان میدهد که چگونه درخواست را با عقبنشینی نمایی انجام دهید:
import json import time import urllib.error import urllib.parse import urllib.request # The maps_key defined below 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 we didn't get an IOError then parse the result. result = json.load(response) if result["status"] == "OK": return result["timeZoneId"] elif result["status"] != "UNKNOWN_ERROR": # Many API errors cannot be fixed by a retry, e.g. INVALID_REQUEST or # ZERO_RESULTS. There is no point retrying 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 each time we retry. if __name__ == "__main__": tz = timezone(39.6034810, -119.6822510, 1331161200) print(f"Timezone: {tz}")
همچنین باید مراقب باشید که کد تکرار مجدد در زنجیره فراخوانی برنامه بالاتر نباشد، زیرا این امر منجر به درخواستهای مکرر در توالی سریع میشود.
درخواستهای همگامسازیشده
تعداد زیاد درخواستهای همگامسازیشده به «میاناهای برنامهسازی کاربردی Google» میتواند شبیه حمله «انکار سرویس توزیعشده» (DDoS) به زیرساخت Google باشد و براساس آن رفتار شود. برای اجتناب از این امر، باید مطمئن شوید که درخواستهای API بین کارخواهها همگامسازی نمیشوند.
برای مثال، برنامهای را درنظر بگیرید که زمان را در منطقه زمانی کنونی نمایش میدهد. این برنامه احتمالاً زنگ هشداری در سیستمعامل کارخواه تنظیم میکند که آن را در ابتدای دقیقه بیدار میکند تا زمان نمایشدادهشده بهروز شود. برنامه نباید هیچگونه فراخوانی میانای برنامهسازی کاربردی را بهعنوان بخشی از پردازش مرتبط با آن هشدار انجام دهد.
انجام تماسهای API در پاسخ به زنگ هشداری ثابت بد است زیرا باعث میشود تماسهای API با شروع دقیقه همزمان شوند، حتی بین دستگاههای مختلف، بهجای اینکه بهطور یکنواخت در طول زمان توزیع شوند. برنامهای که طراحی ضعیفی داشته باشد و این کار را انجام دهد، در ابتدای هر دقیقه، افزایش ناگهانی ترافیک تا شصت برابر سطح عادی ایجاد میکند.
درعوض، یکی از طراحیهای خوب ممکن است این باشد که زنگ هشدار دومی را برای زمان تصادفی تنظیم کنید. وقتی این زنگ دوم بهصدا درمیآید، برنامه هر میانای برنامهسازی کاربردی را که نیاز دارد فراخوانی میکند و نتایج را ذخیره میکند. وقتی برنامه میخواهد نمایش خود را در ابتدای دقیقه بهروز کند، از نتایج ذخیرهشده قبلی استفاده میکند و دوباره API را فراخوانی نمیکند. با این رویکرد، تماسهای میانای برنامهسازی کاربردی بهطور یکنواخت درطول زمان توزیع میشوند. علاوهبراین، فراخوانهای API هنگام بهروزرسانی نمایشگر، پردازش را بهتأخیر نمیاندازند.
بهغیراز ابتدای دقیقه، زمانهای همگامسازی رایج دیگری که باید مراقب باشید هدفیابی نکنید ابتدای ساعت و ابتدای هر روز در نیمهشب است.
درحال پردازش پاسخها
این بخش درباره نحوه استخراج پویا این مقادیر از پاسخهای سرویس وب بحث میکند.
خدمات وب Google Maps پاسخهایی ارائه میدهد که درک آنها آسان است، اما دقیقاً کاربرپسند نیستند. هنگام اجرای پُرسمان، بهجای نمایش مجموعهای از دادهها، احتمالاً میخواهید چند مقدار خاص را استخراج کنید. بهطورکلی، میخواهید پاسخهای سرویس وب را تجزیه کنید و فقط مقادیر موردعلاقهتان را استخراج کنید.
طرح تجزیه مورداستفاده شما بستگی به این دارد که آیا برونداد را در XML یا JSON برمیگردانید. پاسخهای JSON، که درحالحاضر بهشکل اشیاء جاوا اسکریپت هستند، ممکن است در خود جاوا اسکریپت در سمت کارخواه پردازش شوند. پاسخهای XML باید بااستفاده از پردازنده XML و زبان پُرسمان XML پردازش شوند تا عناصر درون قالب XML را خطاب کنند. ما از XPath در نمونههای زیر استفاده میکنیم، زیرا معمولاً در کتابخانههای پردازش XML پشتیبانی میشود.
پردازش XML با XPath
XML یک قالب اطلاعات ساختاریافته نسبتاً بالغ است که برای
تبادل داده استفاده میشود. اگرچه به سبکی JSON نیست، اما XML
از زبانهای بیشتری پشتیبانی میکند و ابزارهای قدرتمندتری دارد. برای مثال، کد پردازش XML در Java در بستههای javax.xml تعبیه شده است.
هنگام پردازش پاسخهای XML، باید از زبان پُرسمان مناسبی برای انتخاب گرهها در سند XML استفاده کنید، نه اینکه فرض کنید عناصر در موقعیتهای مطلق در نشانهگذاری XML قرار دارند. XPath یک زبان نحوی برای توصیف منحصربهفرد گرهها و عناصر در یک سند XML است. عبارتهای XPath به شما امکان میدهند محتوای خاصی را در سند پاسخ XML شناسایی کنید.
عبارات XPath
آشنایی با XPath کمک زیادی به توسعه یک طرح تجزیه قوی میکند. این بخش بر نحوه خطاب کردن عناصر در سند XML با XPath تمرکز میکند و به شما امکان میدهد چندین عنصر را خطاب کنید و پُرسمانهای پیچیده بسازید.
XPath از عبارتها برای انتخاب عناصر در سند XML استفاده میکند و از دستورزبانی مشابه با دستورزبانی که برای مسیرهای دایرکتوری استفاده میشود بهره میبرد. این عبارتها عناصر را در درخت سند XML شناسایی میکنند، که درختی سلسلهمراتبی مشابه درخت DOM است. بهطورکلی، عبارتهای XPath حریص هستند، یعنی با همه گرههایی که با معیارهای ارائهشده مطابقت دارند مطابقت پیدا میکنند.
از XML انتزاعی زیر برای نشان دادن مثالهایمان استفاده خواهیم کرد:
<WebServiceResponse> <status>OK</status> <result> <type>sample</type> <name>Sample XML</name> <location> <lat>37.4217550</lat> <lng>-122.0846330</lng> </location> </result> <result> <message>The secret message</message> </result> </WebServiceResponse>
انتخاب گره در «حالتهای چهره»
انتخابهای XPath گرهها را انتخاب میکنند. گره ریشه
کل سند را دربرمیگیرد. این گره را بااستفاده از عبارت ویژه «/» انتخاب میکنید. توجه داشته باشید که گره ریشه گره سطح بالای سند XML شما نیست؛ درواقع، یک سطح بالاتر از این عنصر سطح بالا قرار دارد و آن را دربرمیگیرد.
گرههای عنصر نشاندهنده عناصر مختلف در درخت سند XML هستند. عنصر <WebServiceResponse>،
برای مثال، نشاندهنده عنصر سطح بالای برگشتی در
سرویس نمونه ما در بالا است. گرههای تکی را ازطریق مسیرهای مطلق یا نسبی انتخاب میکنید که با وجود یا عدم وجود نویسه «/» در ابتدا مشخص میشود.
- مسیر مطلق: عبارت «
/WebServiceResponse/result» همه گرههای<result>را که فرزندان گره<WebServiceResponse>هستند انتخاب میکند. (توجه داشته باشید که هر دو این عناصر از گره ریشه «/» منشعب میشوند.) - مسیر نسبی از بافت کنونی: عبارت
«
result» با هر عنصر<result>در بافت کنونی مطابقت دارد. بهطورکلی، نباید نگران بافت باشید، زیرا معمولاً نتایج سرویس وب را ازطریق یک عبارت واحد پردازش میکنید.
هریک از این عبارتها ممکن است ازطریق افزودن مسیر نویسه عام، که با دو خط مورب («//») نشان داده میشود، تقویت شود.
این نویسه عام نشان میدهد که صفر یا چند عنصر ممکن است در مسیر مداخلهای مطابقت داشته باشند. برای مثال، عبارت XPath «//formatted_address»
با همه گرههای آن نام در سند فعلی مطابقت خواهد داشت.
عبارت //viewport//lat با همه عناصر <lat> که میتوانند <viewport> را بهعنوان والد ردیابی کنند مطابقت دارد.
بهطور پیشفرض، عبارتهای XPath با همه عناصر مطابقت دارند. با ارائه گزاره که در قلاب ([]) قرار میگیرد، میتوانید عبارت را محدود کنید تا با عنصر خاصی مطابقت داشته باشد. برای مثال، عبارت XPath «/GeocodeResponse/result[2] همیشه نتیجه دوم را برمیگرداند.
| نوع عبارت | |
|---|---|
| گره ریشه | عبارت XPath: «
/»انتخاب:
<WebServiceResponse>
<status>OK</status>
<result>
<type>sample</type>
<name>Sample XML</name>
<location>
<lat>37.4217550</lat>
<lng>-122.0846330</lng>
</location>
</result>
<result>
<message>The secret message</message>
</result>
</WebServiceResponse>
|
| مسیر مطلق | عبارت XPath: «
/WebServiceResponse/result»انتخاب:
<result>
<type>sample</type>
<name>Sample XML</name>
<location>
<lat>37.4217550</lat>
<lng>-122.0846330</lng>
</location>
</result>
<result>
<message>The secret message</message>
</result>
|
| مسیر با کارت جایگزین | عبارت XPath: «
/WebServiceResponse//location»انتخاب:
<location>
<lat>37.4217550</lat>
<lng>-122.0846330</lng>
</location>
|
| مسیر با گزاره | عبارت XPath: «
/WebServiceResponse/result[2]/message»انتخاب:
<message>The secret message</message>
|
همه فرزندان مستقیم result اول |
عبارت XPath: «
/WebServiceResponse/result[1]/*»انتخاب:
<type>sample</type>
<name>Sample XML</name>
<location>
<lat>37.4217550</lat>
<lng>-122.0846330</lng>
</location>
|
name
result که نوشتار type آن «نمونه» است. |
عبارت XPath: «
/WebServiceResponse/result[type/text()='sample']/name»انتخاب:
Sample XML
|
توجه به این نکته مهم است که هنگام انتخاب عناصر، گرهها را انتخاب میکنید، نه فقط نوشتار درون آن اشیاء. بهطور کلی، شما میخواهید روی همه گرههای منطبق تکرار کنید و نوشتار را استخراج کنید. همچنین میتوانید گرههای نوشتاری را مستقیماً مطابقت دهید؛ به گرههای نوشتاری در زیر مراجعه کنید.
توجه داشته باشید که XPath از گرههای مشخصه نیز پشتیبانی میکند؛ بااینحال، همه خدمات وب Google Maps عناصر را بدون مشخصه ارائه میکنند، بنابراین تطبیق مشخصهها ضروری نیست.
انتخاب نوشتار در «عبارات»
نوشتار درون سند XML در عبارتهای XPath
ازطریق عامل گره نوشتاری مشخص میشود. این عملگر «text()»
نشاندهنده استخراج نوشتار از گره مشخصشده است. برای مثال،
عبارت XPath «//formatted_address/text()»
همه نوشتار را در عناصر <formatted_address>
برمیگرداند.
| نوع عبارت | |
|---|---|
| همه گرههای نوشتاری (ازجمله فضای سفید) | عبارت XPath: «
//text()»انتخاب:
sample
Sample XML
37.4217550
-122.0846330
The secret message
|
| انتخاب نوشتار | عبارت XPath: «
/WebServiceRequest/result[2]/message/text()»انتخاب:
The secret message
|
| انتخاب حساس به بافت | عبارت XPath: «
/WebServiceRequest/result[type/text() = 'sample']/name/text()»انتخاب:
Sample XML
|
یا میتوانید عبارتی را ارزیابی کنید و مجموعهای از گرهها را برگردانید و سپس آن «مجموعه گره» را تکرار کنید و نوشتار را از هر گره استخراج کنید. در مثال زیر از این رویکرد استفاده میکنیم.
برای اطلاعات بیشتر درباره XPath، به مشخصات XPath W3C مراجعه کنید.
درحال ارزیابی XPath در Java
جاوا پشتیبانی گستردهای از تجزیه XML و استفاده از عبارات XPath
در بسته javax.xml.xpath.* دارد.
به همین دلیل، کد نمونه در این بخش از Java برای نشان دادن نحوه مدیریت XML و تجزیه دادهها از پاسخهای سرویس XML استفاده میکند.
برای استفاده از XPath در کد Java، ابتدا باید نمونهای از XPathFactory را ایجاد کنید و newXPath() را در آن کارخانه فراخوانی کنید تا شیء XPath
ایجاد شود. سپس این شیء میتواند عبارات XML
و XPath را بااستفاده از روش evaluate() پردازش کند.
هنگام ارزیابی عبارات XPath، مطمئن شوید که روی هر «مجموعه گره» احتمالی که ممکن است برگردانده شود، تکرار کنید. ازآنجاییکه این نتایج بهعنوان گرههای DOM در کد Java برگردانده میشوند، باید چنین مقادیر متعددی را در یک شیء NodeList ضبط کنید و روی آن شیء تکرار کنید تا هرگونه نوشتار یا مقداری را از آن گرهها استخراج کنید.
کد زیر نشان میدهد که چگونه یک XPath
شیء ایجاد کنید، به آن XML و عبارت XPath اختصاص دهید، و عبارت را
ارزیابی کنید تا محتوای مربوطه را چاپ کنید.
import org.xml.sax.InputSource; import org.w3c.dom.*; import javax.xml.xpath.*; import java.io.*; public class SimpleParser { public static void main(String[] args) throws IOException { XPathFactory factory = XPathFactory.newInstance(); XPath xpath = factory.newXPath(); try { System.out.print("Web Service Parser 1.0\n"); // In practice, you'd retrieve your XML via an HTTP request. // Here we simply access an existing file. File xmlFile = new File("XML_FILE"); // The xpath evaluator requires the XML be in the format of an InputSource InputSource inputXml = new InputSource(new FileInputStream(xmlFile)); // Because the evaluator may return multiple entries, we specify that the expression // return a NODESET and place the result in a NodeList. NodeList nodes = (NodeList) xpath.evaluate("XPATH_EXPRESSION", inputXml, XPathConstants.NODESET); // We can then iterate over the NodeList and extract the content via getTextContent(). // NOTE: this will only return text for element nodes at the returned context. for (int i = 0, n = nodes.getLength(); i < n; i++) { String nodeString = nodes.item(i).getTextContent(); System.out.print(nodeString); System.out.print("\n"); } } catch (XPathExpressionException ex) { System.out.print("XPath Error"); } catch (FileNotFoundException ex) { System.out.print("File Error"); } } }