مكتبة Requests: دليلك الشامل للتعامل مع واجهات برمجة التطبيقات (APIs)


مكتبة Requests: دليلك الشامل للتعامل مع واجهات برمجة التطبيقات (APIs)

مقدمة

في هذا الدرس، سنتعلم كيفية استخدام مكتبة Requests في بايثون للتفاعل مع واجهات برمجة التطبيقات (APIs) بشكل احترافي، من إرسال الطلبات البسيطة إلى التعامل مع البيانات المعقدة.

الخطوة 1: تثبيت المكتبة وإجراء طلب GET بسيط

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

أولاً، قم بتثبيت المكتبة:

pip install requests

الآن، لنقم بطلب GET:

import requests # استيراد مكتبة requests

# تحديد عنوان URL لواجهة برمجة تطبيقات عامة (مثال: JSONPlaceholder)
API_URL = "https://jsonplaceholder.typicode.com/posts/1"

try:
    # إرسال طلب GET إلى عنوان URL المحدد
    response = requests.get(API_URL)

    # التحقق من حالة الاستجابة (200 تعني نجاح الطلب)
    if response.status_code == 200:
        print("تم استلام البيانات بنجاح!")
        print(f"رمز الحالة: {response.status_code}")
        print(f"نوع المحتوى: {response.headers['Content-Type']}")
        # طباعة أول 100 حرف من محتوى الاستجابة لعدم إغراق الشاشة
        print(f"محتوى الاستجابة (أول 100 حرف):\n{response.text[:100]}...")
    else:
        print(f"حدث خطأ أثناء استلام البيانات. رمز الحالة: {response.status_code}")
        print(f"رسالة الخطأ: {response.text}")

except requests.exceptions.RequestException as e:
    # التعامل مع الأخطاء المتعلقة بالشبكة أو الطلب نفسه
    print(f"حدث خطأ في الاتصال: {e}")
ملاحظة تقنية: مكتبة Requests تبسط التعامل مع HTTP حيث لا تحتاج للقلق بشأن التفاصيل المعقدة مثل Keep-Alive وفك ضغط المحتوى، فهي تديرها تلقائياً.

الخطوة 2: التعامل مع بيانات JSON ومعالجة الأخطاء

معظم واجهات برمجة التطبيقات الحديثة ترجع البيانات بصيغة JSON. سنتعلم كيفية تحليل هذه البيانات والتعامل مع الأخطاء المحتملة بشكل أكثر تفصيلاً.

import requests
import json # لاستخدام وظائف JSON المتقدمة إذا لزم الأمر

API_URL = "https://jsonplaceholder.typicode.com/posts/1"

try:
    response = requests.get(API_URL)
    response.raise_for_status() # ترفع استثناء HTTPError إذا كانت حالة الاستجابة خطأ (4xx أو 5xx)

    # التحقق من أن الاستجابة بصيغة JSON قبل محاولة تحليلها
    if 'application/json' in response.headers.get('Content-Type', ''):
        data = response.json() # تحليل محتوى JSON إلى كائن بايثون (قاموس أو قائمة)

        print("\n===== تفاصيل المنشور =====")
        print(f"معرف المستخدم: {data.get('userId')}") # استخدام .get لتجنب KeyError إذا كان المفتاح غير موجود
        print(f"المعرف: {data.get('id')}")
        print(f"العنوان: {data.get('title')}")
        print(f"النص: {data.get('body')[:50]}...") # طباعة جزء من النص
    else:
        print("الاستجابة ليست بصيغة JSON.")
        print(f"محتوى الاستجابة: {response.text}")

except requests.exceptions.HTTPError as http_err:
    print(f"خطأ HTTP: {http_err} - {http_err.response.text}") # طباعة تفاصيل الخطأ HTTP
except requests.exceptions.ConnectionError as conn_err:
    print(f"خطأ في الاتصال: {conn_err}") # خطأ في الشبكة (DNS، رفض الاتصال، إلخ)
except requests.exceptions.Timeout as timeout_err:
    print(f"انتهت مهلة الطلب: {timeout_err}") # الطلب تجاوز الوقت المحدد
except requests.exceptions.RequestException as req_err:
    print(f"حدث خطأ عام في الطلب: {req_err}") # أي خطأ آخر من مكتبة requests
except json.JSONDecodeError as json_err:
    print(f"خطأ في تحليل JSON: {json_err}") # إذا كانت الاستجابة غير صالحة كـ JSON
ملاحظة تقنية: التابع response.raise_for_status() هو طريقة سريعة للتحقق من نجاح الطلب، حيث يرفع استثناء HTTPError لأي رمز حالة 4xx أو 5xx، مما يبسط معالجة الأخطاء.

الخطوة 3: إرسال بيانات (POST) وتمرير المعاملات (Parameters)

بالإضافة إلى استرجاع البيانات (GET)، غالباً ما نحتاج إلى إرسالها إلى الخادم (مثل إنشاء سجل جديد). سنوضح كيفية إجراء طلب POST مع بيانات JSON، وكيفية تمرير المعاملات في طلب GET.

import requests

# ----- مثال على طلب POST لإنشاء مورد جديد -----
POST_URL = "https://jsonplaceholder.typicode.com/posts"

# البيانات التي سيتم إرسالها في جسم الطلب (بصيغة قاموس بايثون)
new_post_data = {
    "title": "عنوان منشور جديد من بايثون",
    "body": "محتوى منشور تجريبي تم إنشاؤه باستخدام مكتبة Requests.",
    "userId": 1
}

try:
    # إرسال طلب POST. مكتبة requests تقوم بتحويل القاموس إلى JSON وتعيين Content-Type تلقائياً
    post_response = requests.post(POST_URL, json=new_post_data)
    post_response.raise_for_status() # التحقق من نجاح الطلب

    print("\n===== نتيجة طلب POST =====")
    print(f"رمز الحالة: {post_response.status_code}") # عادة 201 Created عند النجاح
    print("المنشور الجديد:")
    print(post_response.json()) # طباعة الاستجابة التي غالباً ما تحتوي على المورد المنشأ ومعرفه

except requests.exceptions.RequestException as e:
    print(f"خطأ في طلب POST: {e}")

# ----- مثال على طلب GET مع المعاملات (Parameters) -----
PARAMS_URL = "https://jsonplaceholder.typicode.com/comments"

# المعاملات التي سيتم إرسالها كاستعلام (query string) في عنوان URL
# ستصبح: ?postId=1&id=2
query_params = {
    "postId": 1,
    "id": 2
}

try:
    # إرسال طلب GET مع المعاملات
    params_response = requests.get(PARAMS_URL, params=query_params)
    params_response.raise_for_status()

    print("\n===== نتيجة طلب GET مع المعاملات =====")
    print(f"عنوان URL المرسل: {params_response.url}") # يعرض عنوان URL النهائي مع المعاملات
    print(f"رمز الحالة: {params_response.status_code}")
    print("التعليقات المطابقة:")
    print(params_response.json()) # طباعة التعليقات التي تطابق المعاملات

except requests.exceptions.RequestException as e:
    print(f"خطأ في طلب GET بالمعاملات: {e}")
ملاحظة تقنية: عند استخدام json=data في طلبات POST، تقوم مكتبة Requests تلقائياً بتعيين رأس Content-Type إلى application/json. أما عند استخدام data=data، فإنها ترسل البيانات كـ application/x-www-form-urlencoded.

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

إليك الكود المجمع الذي يوضح جميع المفاهيم التي تناولناها في هذا الدرس:

import requests
import json

# ----- الخطوة 1: طلب GET بسيط ومعالجة الأخطاء الأساسية -----
print("\n--- الخطوة 1: طلب GET بسيط ---")
API_GET_URL = "https://jsonplaceholder.typicode.com/posts/1"

try:
    response = requests.get(API_GET_URL)
    if response.status_code == 200:
        print(f"GET ناجح: رمز الحالة {response.status_code}")
        print(f"أول 50 حرف من المحتوى: {response.text[:50]}...")
    else:
        print(f"GET فشل: رمز الحالة {response.status_code}")
except requests.exceptions.RequestException as e:
    print(f"خطأ في الاتصال (GET): {e}")

# ----- الخطوة 2: تحليل JSON ومعالجة الأخطاء المتقدمة -----
print("\n--- الخطوة 2: تحليل JSON ومعالجة الأخطاء ---")
API_JSON_URL = "https://jsonplaceholder.typicode.com/posts/2"

try:
    response = requests.get(API_JSON_URL)
    response.raise_for_status() # ترفع استثناء لأخطاء HTTP

    if 'application/json' in response.headers.get('Content-Type', ''):
        data = response.json()
        print(f"JSON تم تحليله بنجاح. عنوان المنشور: {data.get('title')}")
    else:
        print("الاستجابة ليست JSON في الخطوة 2.")

except requests.exceptions.HTTPError as http_err:
    print(f"خطأ HTTP (JSON): {http_err}")
except requests.exceptions.ConnectionError as conn_err:
    print(f"خطأ في الاتصال (JSON): {conn_err}")
except json.JSONDecodeError as json_err:
    print(f"خطأ في تحليل JSON (JSON): {json_err}")
except requests.exceptions.RequestException as req_err:
    print(f"خطأ عام (JSON): {req_err}")

# ----- الخطوة 3: طلب POST وإرسال المعاملات -----
print("\n--- الخطوة 3: طلب POST ومعاملات GET ---")

# طلب POST
POST_URL = "https://jsonplaceholder.typicode.com/posts"
new_post_data = {"title": "منشور جديد", "body": "محتوى تجريبي", "userId": 1}

try:
    post_response = requests.post(POST_URL, json=new_post_data)
    post_response.raise_for_status()
    print(f"POST ناجح: رمز الحالة {post_response.status_code}. ID المنشور: {post_response.json().get('id')}")
except requests.exceptions.RequestException as e:
    print(f"خطأ في طلب POST: {e}")

# طلب GET مع المعاملات
PARAMS_URL = "https://jsonplaceholder.typicode.com/comments"
query_params = {"postId": 1, "id": 5}

try:
    params_response = requests.get(PARAMS_URL, params=query_params)
    params_response.raise_for_status()
    print(f"GET بالمعاملات ناجح: رمز الحالة {params_response.status_code}")
    print(f"التعليق المطابق: {params_response.json()[0].get('body')[:50]}...")
except requests.exceptions.RequestException as e:
    print(f"خطأ في طلب GET بالمعاملات: {e}")

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

عند تشغيل الكود النهائي، ستشاهد مخرجات شبيهة بما يلي على الطرفية (قد تختلف تفاصيل مثل معرفات المنشورات أو التعليقات):

--- الخطوة 1: طلب GET بسيط ---
GET ناجح: رمز الحالة 200
أول 50 حرف من المحتوى: {"userId": 1, "id": 1, "title": "sunt aut facere repellat pro...

--- الخطوة 2: تحليل JSON ومعالجة الأخطاء ---
JSON تم تحليله بنجاح. عنوان المنشور: qui est esse

--- الخطوة 3: طلب POST ومعاملات GET ---
POST ناجح: رمز الحالة 201. ID المنشور: 101
GET بالمعاملات ناجح: رمز الحالة 200
التعليق المطابق: nesciunt quas odio

يوضح هذا الإخراج أن جميع الطلبات قد تمت بنجاح، وتم تحليل البيانات وتمريرها بشكل صحيح، وتم التعامل مع الأخطاء المحتملة.