مشروع مصغر: بناء أداة لجلب حالة الطقس المباشرة عبر API خارجي


مشروع مصغر: بناء أداة لجلب حالة الطقس المباشرة عبر API خارجي

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

سنغطي أساسيات التعامل مع الـ APIs، إرسال الطلبات، وتحليل البيانات المسترجعة لعرض معلومات مفيدة للمستخدم.

الخطوة 1: تهيئة البيئة والحصول على مفتاح API

لبناء أداتنا، سنحتاج إلى مكتبة requests في بايثون، والتي تسهل عملية إرسال طلبات HTTP واستقبال الردود. كما سنحتاج إلى مفتاح API من خدمة طقس خارجية.

أولاً، قم بتثبيت مكتبة requests إذا لم تكن مثبتة بالفعل:

pip install requests

ملاحظة تقنية: للحصول على مفتاح API، يمكنك التسجيل مجاناً في خدمات مثل OpenWeatherMap (api.openweathermap.org). بعد التسجيل، ستجد مفتاح API الخاص بك في لوحة التحكم. احفظ هذا المفتاح جيداً، فهو ضروري لمصادقة طلباتك.

الخطوة 2: بناء طلب API الأساسي وإرساله

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

import requests # استيراد مكتبة requests للتعامل مع طلبات HTTP

API_KEY = "YOUR_API_KEY" # استبدل هذا بمفتاح API الخاص بك من OpenWeatherMap
BASE_URL = "http://api.openweathermap.org/data/2.5/weather" # رابط الـ API الأساسي للطقس

def get_weather(city_name):
    # تعريف المعاملات (parameters) التي سترسل مع الطلب
    params = {
        'q': city_name, # اسم المدينة
        'appid': API_KEY, # مفتاح الـ API الخاص بنا
        'units': 'metric', # لطلب درجة الحرارة بوحدة مئوية (Celsius). يمكن استخدام 'imperial' للفهرنهايت أو حذفها للكلفن.
        'lang': 'ar' # لطلب وصف الطقس باللغة العربية
    }
    
    try:
        # إرسال طلب GET إلى الـ API مع المعاملات المحددة
        response = requests.get(BASE_URL, params=params)
        # رفع استثناء إذا كان هناك خطأ في استجابة HTTP (مثل 404 أو 500)
        response.raise_for_status()
        return response.json() # إرجاع الاستجابة بصيغة JSON
    except requests.exceptions.HTTPError as http_err:
        print(f"خطأ HTTP: {http_err}") # طباعة رسالة خطأ HTTP
        return None
    except requests.exceptions.RequestException as req_err:
        print(f"حدث خطأ أثناء الطلب: {req_err}") # طباعة رسالة خطأ عامة للطلب
        return None

# مثال على كيفية استخدام الدالة (سيتم تشغيله لاحقاً في الكود الكامل)
# weather_data = get_weather("London")
# if weather_data: print(weather_data)

ملاحظة تقنية: استخدام response.raise_for_status() يساعد في اكتشاف الأخطاء الشائعة مثل عدم وجود المدينة أو مشكلة في مفتاح الـ API عن طريق رفع استثناء.

الخطوة 3: تحليل البيانات وعرض النتائج

بعد استلام الاستجابة بصيغة JSON، نحتاج إلى تحليلها لاستخراج المعلومات المهمة مثل درجة الحرارة، الوصف، والرطوبة. ثم سنقوم بعرضها بشكل منظم للمستخدم.

# ... (الكود السابق من الخطوة 2 يتم تضمينه هنا)

def display_weather(weather_data):
    if weather_data is None:
        print("تعذر الحصول على بيانات الطقس.")
        return

    # التحقق مما إذا كانت المدينة موجودة في الاستجابة
    if weather_data.get("cod") == "404":
        print("عذراً، لم يتم العثور على المدينة المطلوبة.")
        return

    try:
        city = weather_data['name'] # اسم المدينة من الاستجابة
        temperature = weather_data['main']['temp'] # درجة الحرارة
        description = weather_data['weather'][0]['description'] # وصف الطقس
        humidity = weather_data['main']['humidity'] # نسبة الرطوبة
        wind_speed = weather_data['wind']['speed'] # سرعة الرياح

        # طباعة معلومات الطقس بشكل منسق
        print(f"\nالطقس في {city}:")
        print(f"درجة الحرارة: {temperature:.1f}°م") # تنسيق درجة الحرارة لكسر عشري واحد
        print(f"الوصف: {description.capitalize()}") # جعل الحرف الأول من الوصف كبيراً
        print(f"الرطوبة: {humidity}%")
        print(f"سرعة الرياح: {wind_speed} متر/ثانية")

    except KeyError as e:
        print(f"خطأ في تحليل البيانات: مفتاح مفقود {e}") # التعامل مع الأخطاء إذا كانت بنية JSON مختلفة
    except Exception as e:
        print(f"حدث خطأ غير متوقع: {e}") # التعامل مع أي أخطاء أخرى

# دالة رئيسية لتشغيل التطبيق
def main():
    city = input("أدخل اسم المدينة: ") # طلب اسم المدينة من المستخدم
    weather_data = get_weather(city) # جلب بيانات الطقس
    display_weather(weather_data) # عرض بيانات الطقس

# التأكد من أن الدالة main() تعمل فقط عند تشغيل السكربت مباشرة
if __name__ == "__main__":
    main()

الكود النهائي الكامل

إليك السكربت الكامل الذي يجمع جميع الخطوات المذكورة أعلاه. تذكر استبدال "YOUR_API_KEY" بمفتاح API الخاص بك.

import requests

API_KEY = "YOUR_API_KEY" # استبدل هذا بمفتاح API الخاص بك من OpenWeatherMap
BASE_URL = "http://api.openweathermap.org/data/2.5/weather"

def get_weather(city_name):
    params = {
        'q': city_name,
        'appid': API_KEY,
        'units': 'metric',
        'lang': 'ar'
    }
    
    try:
        response = requests.get(BASE_URL, params=params)
        response.raise_for_status() # رفع استثناء لأخطاء HTTP (4xx أو 5xx)
        return response.json()
    except requests.exceptions.HTTPError as http_err:
        if response.status_code == 404:
            print("عذراً، لم يتم العثور على المدينة المطلوبة. يرجى التحقق من الاسم.")
        elif response.status_code == 401:
            print("خطأ: مفتاح API غير صالح أو غير مصرح به. يرجى التحقق من مفتاح API الخاص بك.")
        else:
            print(f"خطأ HTTP: {http_err} - رمز الحالة: {response.status_code}")
        return None
    except requests.exceptions.RequestException as req_err:
        print(f"حدث خطأ أثناء الطلب: {req_err}. يرجى التحقق من اتصالك بالإنترنت.")
        return None

def display_weather(weather_data):
    if weather_data is None:
        print("تعذر الحصول على بيانات الطقس.")
        return

    try:
        city = weather_data['name']
        temperature = weather_data['main']['temp']
        description = weather_data['weather'][0]['description']
        humidity = weather_data['main']['humidity']
        wind_speed = weather_data['wind']['speed']

        print(f"\nالطقس في {city}:")
        print(f"درجة الحرارة: {temperature:.1f}°م")
        print(f"الوصف: {description.capitalize()}")
        print(f"الرطوبة: {humidity}%")
        print(f"سرعة الرياح: {wind_speed} متر/ثانية")

    except KeyError as e:
        print(f"خطأ في تحليل البيانات: مفتاح مفقود {e}. قد تكون بنية الاستجابة غير متوقعة.")
    except Exception as e:
        print(f"حدث خطأ غير متوقع أثناء عرض البيانات: {e}")

def main():
    city = input("أدخل اسم المدينة: ")
    weather_data = get_weather(city)
    display_weather(weather_data)

if __name__ == "__main__":
    main()

النتيجة المتوقعة

عند تشغيل السكربت، سيطلب منك إدخال اسم المدينة. بعد إدخال المدينة والضغط على Enter، سيتصل السكربت بواجهة برمجة تطبيقات الطقس ويعرض لك تفاصيل الطقس الحالية لتلك المدينة. إليك مثال على النتيجة المتوقعة:

أدخل اسم المدينة: London

الطقس في London:
درجة الحرارة: 15.2°م
الوصف: غيوم متفرقة
الرطوبة: 88%
سرعة الرياح: 2.5 متر/ثانية

إذا أدخلت مدينة غير موجودة، فستتلقى رسالة خطأ مناسبة مثل:

أدخل اسم المدينة: NonExistentCity
عذراً، لم يتم العثور على المدينة المطلوبة. يرجى التحقق من الاسم.
تعذر الحصول على بيانات الطقس.