Skip to main content

Welcome to a Grasp lesson

Create a free account to keep studying and create your own study path.

Lesson 13

معالجة وتحليل استجابات JSON من الـ APIs

Recommended resources

أهلاً بك مجدداً في رحلتك لبناء وكلاء الذكاء الاصطناعي!

في درسنا السابق، قمنا بالخطوة الأولى والمثيرة للتواصل مع الإنترنت عبر كود بايثون. تعلمنا كيف نرسل طلبات GET لجلب البيانات وPOST لإنشاء بيانات جديدة باستخدام مكتبة requests. ورأينا كيف أن الدالة response.json() تحول الرد القادم من الخادم إلى قاموس بايثون يمكننا التعامل معه.

اليوم، سنتعمق أكثر في هذه الخطوة الأخيرة. ففي كثير من الأحيان، لا تكون البيانات التي نتلقاها مجرد قاموس بسيط. قد تكون قائمة طويلة من العناصر، أو قاموساً يحتوي على قواميس أخرى بداخله. هدفنا اليوم هو أن نتعلم كيف "نشرح" هذه الاستجابات المعقدة ونستخرج منها المعلومات التي نحتاجها بدقة. هذه المهارة ضرورية جداً، لأن وكيل الذكاء الاصطناعي يعتمد على قدرته على فهم البيانات التي يحصل عليها من أدواته (مثل واجهات برمجة التطبيقات) لاتخاذ قرارات ذكية.

لنتخيل أننا في الدرس السابق تعلمنا كيف نطلب قائمة الطعام (Request) وكيف نستلمها (Response). اليوم، سنتعلم كيف نقرأ قائمة الطعام هذه بالتفصيل، ونختار منها الطبق الذي نريده بالضبط.

مخطط تدفق طلب واستجابة API مع JSON
هذا الرسم يذكرنا بدورة الطلب والاستجابة التي تعلمناها. اليوم، سنركز على تحليل "جسم JSON" أو `JSON BODY` الذي يأتي في الاستجابة.

1. ما هو تنسيق JSON؟ لغة البيانات المشتركة

عندما تتواصل البرامج المختلفة عبر الإنترنت، فإنها تحتاج إلى لغة مشتركة لتبادل البيانات. التنسيق الأكثر شيوعاً واستخداماً اليوم هو JSON (تُنطق "جيسون")، وهي اختصار لـ JavaScript Object Notation.

ببساطة، JSON هو تنسيق نصي لتمثيل البيانات بطريقة منظمة وسهلة القراءة للبشر والآلات على حد سواء.

العمل مع JSON في بايثون: دليل سهل للمبتدئين

لفهم أساسيات JSON، ألقِ نظرة على المقال التالي من Apidog. سيركز شرحي على النقاط الأساسية التي تحتاجها.

اقرأ فقط القسم الأول بعنوان 'ما هو JSON؟'. ركز على شكل الكود وكيف يشبه قاموس بايثون الذي تعرفه.

كما رأيت في المقال، يتكون JSON من لبنتين أساسيتين:

  • الأزواج (Key-Value Pairs): تماماً مثل قواميس بايثون، يتكون JSON من مفاتيح وقيم ("key": value). المفتاح يكون دائماً نصاً بين علامتي اقتباس مزدوجتين.
  • المصفوفات (Arrays): وهي تماثل القوائم (Lists) في بايثون، وتُكتب بين قوسين مربعين [].

عندما تستلم بايثون بيانات JSON، فإنها تحولها إلى أنواع البيانات التي تفهمها:

  • كائن JSON {...} ⬅️ قاموس بايثون dict
  • مصفوفة JSON [...] ⬅️ قائمة بايثون list
  • نص "..." ⬅️ سلسلة نصية str
  • رقم 123 أو 12.3 ⬅️ عدد صحيح int أو عشري float
  • قيمة منطقية true أو false ⬅️ True أو False
  • القيمة الفارغة null ⬅️ None
بنية JSON: خريطة ذهنية
هذه الخريطة الذهنية تلخص بنية JSON بشكل بصري. لاحظ كيف أن القيمة (Value) يمكن أن تكون من أنواع مختلفة، بما في ذلك كائن (Object) أو مصفوفة (Array) أخرى، مما يسمح ببناء هياكل بيانات متداخلة ومعقدة.


2. كيف تحول بايثون النص إلى بيانات؟

في الدرس السابق، استخدمنا response.json() بسلاسة. لكن ما الذي يحدث خلف الكواليس؟ ما تفعله هذه الدالة هو أخذ النص الخام من استجابة الـ API، والذي يكون بتنسيق JSON، وتحويله (أو "تحليله" - Parsing) إلى كائن بايثون (قاموس أو قائمة).

توفر بايثون وحدة مدمجة تسمى json لهذا الغرض. الدالة الأساسية فيها هي json.loads() (لاحظ حرف s في النها_ية، وهي اختصار لكلمة "string").

لنرى مثالاً بسيطاً:

import json

# لنفترض أن هذا هو النص الذي استلمناه من API
json_string = '{"name": "Ahmed", "is_student": true, "courses": ["Math", "Physics"]}'

# استخدم json.loads() لتحويل النص إلى قاموس بايثون
python_dict = json.loads(json_string)

# الآن python_dict هو قاموس عادي يمكننا التعامل معه
print(python_dict)
print(f"الاسم: {python_dict['name']}")
print(f"عدد المواد: {len(python_dict['courses'])}")

عند تشغيل هذا الكود، ستكون المخرجات:

{'name': 'Ahmed', 'is_student': True, 'courses': ['Math', 'Physics']}
الاسم: Ahmed
عدد المواد: 2

إذن، response.json() هي مجرد طريقة مختصرة ومريحة توفرها مكتبة requests لتنفيذ هذه العملية مباشرة على كائن الاستجابة.

لفهم أعمق، شاهد هذا المقطع القصير الذي يوضح الفرق بين json.loads() (للتعامل مع السلاسل النصية) وjson.load() (للتعامل مع الملفات، والتي سنتطرق لها لاحقاً).

Python Tutorial: Working with JSON Data using the json Module

يشرح هذا الفيديو من Corey Schafer بالتفصيل كيفية استخدام وحدة json في بايثون. على الرغم من أن الفيديو باللغة الإنجليزية، إلا أن الأمثلة البرمجية واضحة جداً وتوضح المفاهيم التي نناقشها.

شاهد من بداية الفيديو حتى الدقيقة 04:27. ركز على: شكل بيانات JSON الأولية كسلسلة نصية (string). كيفية استخدام json.loads() لتحويلها إلى قاموس بايثون. جدول التحويل بين أنواع بيانات JSON وأنواع بيانات بايثون (حوالي الدقيقة 02:00). كيف بدأ بالوصول إلى البيانات بعد تحويلها (مثل الدخول في حلقة تكرارية).



3. التطبيق العملي: تشريح استجابة API

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

السيناريو الأول: التعامل مع قائمة من العناصر

في الدرس السابق، جلبنا منشوراً واحداً (/posts/1). ماذا لو أردنا جلب قائمة بأول 5 منشورات؟ الرابط سيكون https://jsonplaceholder.typicode.com/posts.

import requests

# سنضيف `?_limit=5` في نهاية الرابط ليُرجع لنا 5 عناصر فقط لتسهيل العرض
url = "https://jsonplaceholder.typicode.com/posts?_limit=5"

response = requests.get(url)

# التحقق من نجاح الطلب
if response.status_code == 200:
    # response.json() سيعيد لنا الآن قائمة (list) من القواميس
    posts_list = response.json()
    
    print(f"نوع البيانات المستلمة: {type(posts_list)}")
    print(f"عدد المنشورات المستلمة: {len(posts_list)}")
    print("---")

    # يمكننا الآن استخدام حلقة تكرارية للمرور على كل منشور في القائمة
    for post in posts_list:
        # كل 'post' هو قاموس منفصل
        post_id = post['id']
        post_title = post['title']
        print(f"عنوان المنشور رقم {post_id}: {post_title}")
else:
    print(f"فشل الطلب، رمز الحالة: {response.status_code}")

هذا النمط شائع جداً: تتلقى قائمة، تمر عبرها بحلقة for، ثم تتعامل مع كل عنصر (وهو قاموس) على حدة.

السيناريو الثاني: التعامل مع بيانات متداخلة (Nested Data)

أحياناً، يحتوي القاموس على قواميس أخرى بداخله. لنجلب بيانات مستخدم واحد من الرابط https://jsonplaceholder.typicode.com/users/1.

import requests

url = "https://jsonplaceholder.typicode.com/users/1"

response = requests.get(url)

if response.status_code == 200:
    user_data = response.json()
    
    # الوصول إلى قيمة على المستوى الأول
    user_name = user_data['name']
    user_email = user_data['email']
    print(f"اسم المستخدم: {user_name} ({user_email})")
    
    # الوصول إلى قيمة داخل قاموس متداخل
    # user_data['address'] يعطينا القاموس الخاص بالعنوان
    # ثم نستخدم ['city'] للوصول إلى قيمة المدينة داخل ذلك القاموس
    user_city = user_data['address']['city']
    print(f"المدينة: {user_city}")
    
    # يمكننا حتى الوصول إلى بيانات أعمق!
    geo_lat = user_data['address']['geo']['lat']
    print(f"خط العرض الجغرافي: {geo_lat}")
else:
    print(f"فشل الطلب، رمز الحالة: {response.status_code}")

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

اختبر فهمك!

توفر واجهة JSONPlaceholder نقطة نهاية للتعليقات (comments). جرب إرسال طلب GET إلى الرابط https://jsonplaceholder.typicode.com/comments/1.

الاستجابة التي ستحصل عليها ستكون قاموساً يحتوي على مفاتيح مثل postId, id, name, email, و body.

اكتب برنامجاً صغيراً يقوم بما يلي:

  1. يجلب بيانات التعليق رقم 1.
  2. يطبع جملة بالصيغة التالية: التعليق من [email] يقول: "[body]"، مستخدماً القيم من البيانات التي تم جلبها.
أظهر الإجابة
import requests

url = "https://jsonplaceholder.typicode.com/comments/1"
response = requests.get(url)

if response.status_code == 200:
    comment_data = response.json()
    
    # استخراج البريد الإلكتروني ونص التعليق
    email = comment_data['email']
    body = comment_data['body']
    
    # طباعة الجملة المطلوبة
    print(f"التعليق من {email} يقول: \"{body}\"")
else:
    print(f"فشل الطلب، رمز الحالة: {response.status_code}")


ملخص الدرس وأهم النقاط

أحسنت! لقد اكتسبت اليوم مهارة لا غنى عنها لأي مبرمج يتعامل مع الإنترنت. لم نعد نكتفي باستلام البيانات، بل أصبحنا قادرين على فهمها واستخلاص ما يهمنا منها.

أهم النقاط التي استخلصناها:

  • JSON هو التنسيق القياسي لتبادل البيانات في واجهات برمجة التطبيقات (APIs).
  • يشبه JSON قواميس وقوائم بايثون، مما يسهل التعامل معه.
  • الدالة response.json() تقوم بتحليل نص JSON وتحويله إلى كائن بايثون (عادةً dict أو list).
  • يمكننا التنقل داخل البيانات المعقدة باستخدام:
    • حلقات for للمرور على القوائم.
    • الوصول عبر المفتاح ['key'] للوصول إلى القيم داخل القواميس، حتى لو كانت متداخلة.

ما التالي؟

حتى الآن، كل واجهات برمجة التطبيقات التي تعاملنا معها كانت عامة ومفتوحة للجميع. لكن معظم الـ APIs القوية والمفيدة (مثل واجهات OpenAI، Google Maps, Twitter) تتطلب منك التعريف بنفسك قبل أن تسمح لك بالوصول إلى بياناتها. يتم ذلك عادةً باستخدام ما يسمى "مفتاح API" (API Key).

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