24  الخدمات البرمجية

نتصوَّر الشبكة العالميَّة (الإنْتَرنِت) بأنها مجموعة أجهزة مترابطة بأشكال ارتباطات مختلفة. وكما هي السنة بين الأفراد والمؤسسات أن يخدم بعضهم بعضًا، ويتبادلون المنافع؛ فكذلك صار في العصر الرقمي تخادم عن طريق الحواسيب عبر الشبكة.

وكما أن المعادن موزعة مكامنها في طيات أطراف الأرض؛ فإن البيانات (المواد الخام) والمعلومات (المعالجة) وآليات المعالجة (الأجهزة والخوارزميات) كذلك؛ يتفاضل الناس فيما بينهم فيها. فيكون بينهم تبادل المنافع.

شبكة محليَّة مرتبطة بموجِّه يربطها بشبكة أكبر (الشبكة العالمية) - الصورة من CloudFlare

فالصورة هذه توضِّح أن الشبكة المحليَّة (Local Area Network - LAN) -الذي يكون جهاز أحدنا فردًا من أفرادها- مرتبطةٌ بموجِّه (Router) يكون بمثابة البوابة إلى الشبكات الأخرى. فأي اتصال يكون بيننا وبين العالم يمرُّ عبره.

وأما شبكة الشبكات فتسمى (Wide Area Network - WAN)؛ وهكذا ببساطة نتصوَّر الشبكة العالمية؛ الإنترنت.

الخادم والعميل

وعندما ننظر إلى أفراد التبادلات المعلوماتية بين الحواسيب، فإن أحد الطرفين يكون له دوْر العميل والآخر يكون له دوْر الخادم؛ ثم قد ينعكس الدوْر:

  • فأما الخادم (Server) فيسمى كذلك المزوِّد (Provider) باعتبار المنتَج أو الخدمة البرمجية.
  • وأما العميل (Client) فيسمى كذلك المستخدم (User) أو المستهلك (Consumer).

خادم لعدة عملاء

مكتبة العميل

تسهل بعض المكتبات الوصول إلى خوادم مخصوصة؛ وتسمى المكتبة حينئذٍ عدة تطوير البرمجية (SDK - Software Development Kit)، أو: مكتبة العميل (Client Library).

فأحد طرق التعامل مع الخدمات البرمجية، أن توفِّر هذه الخدمة مكتبةً للاتصال بها، تبدوا كأنها إجراءات مُعرَّفة عاديَّة، لكنَّ تفاصيلها تتضمَّن إرسال طلب للخادم المزوِّد ثم الرجوع بجوابه كقيمة لموضع الاستدعاء.

مكتبة جيوباي مثالاً

ونمثل على ذلك بمكتبة GeoPy حيث كُتِب في الوصف:

جيوباي هو عميل بايثوني لمجموعة من خدمات شائعة على الشبكة للترميز الجغرافي. فهو يسهل تحديد إحداثيات العناوين والمدن والبلدان والمعالم في جميع أنحاء العالم باستخدام برامج ترميز جغرافي خارجية ومصادر بيانات أخرى.

أولاً تثبيت المكتبة باستعمال uv:

uv add geopy

وهذا العميل يمكن ضبطه للاختيار من مجموعة خوادم. وسنختار العميل Nominatim الذي يتصل بمزوِّد خدمة خارجية، وهو مزوِّد خدمة جغرافية عالمية تسمى OpenStreetMap.

from geopy.geocoders import Nominatim

يطلب منَّا الإجراء المنشئ التصريح بهويَّة للتطبيق؛ وذلك بتعيين user_agent، وهذا بحسب ما ورد في توثيق المكتبة. فنكتب أي اسم يدلُّ على التطبيق الذي نعمل عليه الآن، وسنختار الاسم pythonia .. ولك أن تختار أي اسم آخر.

geolocator = Nominatim(user_agent="pythonia")

نفترض أننا نريد معرفة إحداثيات مدينة الدمام، وهذا هو عمل الإجراء geocode:

dammam_location = geolocator.geocode("Dammam, Saudi Arabia")

قد يبدوا الإجراء عاديًّا، لكنه في الواقع يتصل بالخادم المزوِّد ويسأله عن إحداثيات المدينة.

sequenceDiagram
    UserCode -->> GeoPy: .geocode("...")
    GeoPy -->> OpenStreetMap: Request
    OpenStreetMap -->> GeoPy: Response
    GeoPy -->> UserCode: Return

جرب اطبع النتيجة لتعرف ما هو هذا الشيء الذي تتعامل معه. وكذلك اطبع نوعه:

print(dammam_location)
print(type(dammam_location))
الدمام, محافظة الدمام, المنطقة الشرقية, 32242, السعودية
<class 'geopy.location.Location'>

تبيَّن لنا أن النوع هو: geopy.location.Location وبالبحث في توثيق المكتبة، وجدنا تفاصيلها هنا: geopy.location.Location. حيث كُتب:

Contains a parsed geocoder response. Can be iterated over as (location<String>, (latitude<float>, longitude<float>)). Or one can access the properties address, latitude, longitude, or raw. The last is a dictionary of the geocoder’s response for this item.

وبهذا نعرف أنها تتكون من ثلاثة معلومات، ويمكن الوصول لها بطرق مختلفة.

الطريقة الأولى معقدة ولذلك سنتركها.

الطريقة الثانية (عن طريق الصفات):

print(dammam_location.address)
print(dammam_location.latitude)
print(dammam_location.longitude)
الدمام, محافظة الدمام, المنطقة الشرقية, 32242, السعودية
26.4367824
50.1039991

الطريقة الثالثة (عن طريق القاموس):

print(dammam_location.raw)
print(type(dammam_location.raw)) # قاموس
{'place_id': 40859854, 'licence': 'Data © OpenStreetMap contributors, ODbL 1.0. http://osm.org/copyright', 'osm_type': 'node', 'osm_id': 287865393, 'lat': '26.4367824', 'lon': '50.1039991', 'class': 'place', 'type': 'city', 'place_rank': 16, 'importance': 0.5524619823312412, 'addresstype': 'city', 'name': 'الدمام', 'display_name': 'الدمام, محافظة الدمام, المنطقة الشرقية, 32242, السعودية', 'boundingbox': ['26.2767824', '26.5967824', '49.9439991', '50.2639991']}
<class 'dict'>

وكذلك لمدينة أخرى مثل البحرين:

bahrain_location = geolocator.geocode("Bahrain")

ثم بعد أن حصلنا على المعلومات، نستخرج الإحداثيات من المتغيرات التي حصلنا عليها:

dammam_coords = (dammam_location.latitude, dammam_location.longitude)
bahrain_coords = (bahrain_location.latitude, bahrain_location.longitude)

ثم نحسب المسافة بين المدينتين، باستعمال فعل موجود في وحدة geopy.distance، وهو geodesic. وأنبه مرة أخرى أن معرفة مثل ذلك يكون بتصفح فهرس المكتبة.

from geopy.distance import geodesic

distance = geodesic(dammam_coords, bahrain_coords)
print(f"Between Dammam and Bahrain is {distance.kilometers:.2f} km")
Between Dammam and Bahrain is 63.61 km

وهكذا نكون قد حسبنا المسافة بين المدينتين بالكيلومترات، باستعمال مكتبة أعطتنا الإحداثيات للمدينتين، وكذلك أعطتنا معالجة المسافة بينهما.

مفتاح الواجهة البرمجية (API_KEY)

قلنا أن مكتبة العميل هذه تمكِّنك من الوصول إلى عدة خدمات جيومكانية. ويجدر بالذكر أننها تتفاضل في دقة الحساب، وسرعة الجواب، وكمية الطلبات المسموحة إليها.

لذلك قد تضطر لتسجيل حساب وتشحنه بالمال برصيد، ثم تستعمل الخدمة عن طريق هذا الحساب. والطريقة التي يعرف بها الخادم أن البرنامج مخوَّل باستعمال رصيد هذا الحساب هي عبر مفتاح الواجهة البرمجية (API Key).

مكتبة جيوباي وخدمات الترميز الجغرافي

فإن أردت تغيير مزوِّد الخدمة (إما لعدم دقتها أو عدم توفر المعلومات أو أي سبب آخر)، فما عليك إلا استعمال استيراد Geocoder آخر. ونمثل لذلك بعميل يتصل بخدمة TomTom:

from geopy.geocoders import TomTom

geolocator = TomTom(user_agent="pythonia", api_key="...")

لكن هذا يتطلَّب شيئًا إضافيًّا وهو الحصول على مفتاح متعلِّق بحساب مسجَّل على موقع TomTom نفسه. ثم وضع هذا الفتاح هنا. وبهذا المفتاح المرتبط بهذا الحِساب يتمُّ تعبئة الاشتراك والصرف من رصيده.

وهذه أحد مصادر دخل شركات المعلومات.