قبل إطلاق الحملة، يمكنك معالجة قائمة حسابات IG باستخدام نص برمجي والحصول على تقرير JSON يتضمن استجابة API لكل اسم. يعيد مسار IG Scraper API من jsonscraper حالة خارجية وكائنًا للملف الشخصي؛ ويضم المخطط المرصود اسم المستخدم ومؤشرات الخصوصية والتحقق وعدد المنشورات والمتابعين والحسابات التي يتابعها. تساعد هذه الحقول على فرز السجلات التي تحتاج إلى مراجعة يدوية، لكنها لا تفسّر وحدها سبب غياب استجابة أو ورود استجابة غير متوقعة.

المشكلة: تبدو قائمة الحسابات سليمة، لكن هل هي جاهزة للعمل؟
قد تضمّ ورقة عمل الحملة حسابات غيّرت أسماءها وأسماء مستخدمين مكتوبة خطأ وملفات خاصة. إذا بدأ الفريق تحليل القائمة من دون فحص مسبق، فسيتعين على أحدهم فتح الحسابات واحدًا تلو الآخر. يقلل الفحص الآلي العمل اليدوي، وينشئ سجلًا موحدًا لما أعادته API لكل اسم طُلب منها.
هدف هذا السيناريو محدود: المرور على القائمة، وحفظ استجابات HTTP الفعلية وبيانات JSON، وإحالة الملفات التي تتضمن السمات المطلوبة للحملة إلى المراجعة اليدوية. يوثّق التقرير البيانات المرصودة، لكنه لا يحدد سبب عدم إرجاع ملف أو سبب فشل الطلب.
ما الذي يفحصه الطلب
تحدّد وثائق jsonscraper المسار GET \/v1\/user\/by\/username. المعامل المطلوب هو username، ويُمرّر المفتاح عبر license_key. أما المعامل الاختياري cache_timeout فيفعّل التخزين المؤقت للمدة المحددة بالثواني، بينما تُبقي القيمة 0 التخزين معطّلًا. يتضمن المخطط المرصود للاستجابة الناجحة status خارجيًا وكائن ig يحوي حقول الملف الشخصي.
لأغراض التشخيص، افصل بين ثلاث حقائق: هل أمكن تنفيذ طلب HTTP؟ وهل تتضمن بيانات JSON المحلّلة كائن ig؟ وما الحقول الموجودة في ذلك الكائن؟ إذا لم تسر أي مرحلة على النحو المتوقع، فيمكن للنص البرمجي تسجيل النتيجة التقنية والاستجابة الأصلية. وتشير هذه النتيجة إلى ضرورة الفحص، لكنها لا تحدد سبب الإخفاق.
جهّز بيانات الإدخال والمفتاح
أنشئ ملفًا باسم usernames.txt، واكتب اسم مستخدم واحدًا في كل سطر من دون الرمز @. احذف الأسطر الفارغة والتكرارات، وأبقِ فقط الحسابات المرتبطة بالحملة. ولتسهيل مقارنة النتائج لاحقًا، احتفظ بتاريخ الفحص ومعرّف المشروع كلٌّ على حدة.
احفظ المفتاح في متغير بيئة باسم JSONSCRAPER_INSTAGRAM_LICENSE_KEY، وليس في الشيفرة المصدرية أو المستودع:
export JSONSCRAPER_INSTAGRAM_LICENSE_KEY="مفتاحك"
python3 check_profiles.py
يستخدم المثال مكتبة Python 3.8+ القياسية، ولا يتطلب تثبيت حزم HTTP.
مثال: اطلب بيانات الملفات واحفظ تقريرًا
يمرّ النص البرمجي على الأسماء واحدًا تلو الآخر. عند نجاح استجابة JSON، يحفظ متن الاستجابة الفعلي وحقول الملف الشخصي المتاحة؛ وعند وقوع خطأ HTTP أو خطأ شبكي، يسجله بوصفه نتيجة تقنية. تبقى الحقول الغائبة null، ويُحفظ متن الاستجابة الخام إذا أمكن قراءته.
import json
import os
import time
from datetime import datetime, timezone
from urllib.error import HTTPError, URLError
from urllib.parse import urlencode
from urllib.request import Request, urlopen
API_KEY = os.environ.get("JSONSCRAPER_INSTAGRAM_LICENSE_KEY")
if not API_KEY:
raise SystemExit("عيّن JSONSCRAPER_INSTAGRAM_LICENSE_KEY")
BASE_URL = "https:\/\/ig.jsonscraper.com\/v1\/user\/by\/username"
with open("usernames.txt", encoding="utf-8") as f:
usernames = list(dict.fromkeys(
line.strip().lstrip("@") for line in f if line.strip()
))
results = []
for username in usernames:
params = urlencode({"username": username, "license_key": API_KEY})
request = Request(f"{BASE_URL}?{params}", method="GET")
checked_at = datetime.now(timezone.utc).isoformat()
try:
with urlopen(request, timeout=30) as response:
http_status = response.status
raw_body = response.read().decode("utf-8")
try:
payload = json.loads(raw_body)
json_error = None
except json.JSONDecodeError as exc:
payload = None
json_error = str(exc)
profile = payload.get("ig") if isinstance(payload, dict) else None
record = {
"requested_username": username,
"checked_at": checked_at,
"http_status": http_status,
"api_status": payload.get("status") if isinstance(payload, dict) else None,
"check_result": "profile_returned" if isinstance(profile, dict) else "unexpected_or_missing_profile_object",
"response": payload if payload is not None else raw_body,
}
if json_error:
record["json_error"] = json_error
if isinstance(profile, dict):
record["returned_username"] = profile.get("username")
record["is_private"] = profile.get("is_private")
record["is_verified"] = profile.get("is_verified")
record["media_count"] = profile.get("media_count")
record["follower_count"] = profile.get("follower_count")
record["following_count"] = profile.get("following_count")
results.append(record)
except HTTPError as exc:
body = exc.read().decode("utf-8", errors="replace")
results.append({
"requested_username": username,
"checked_at": checked_at,
"check_result": "http_error",
"http_status": exc.code,
"response": body,
})
except (URLError, TimeoutError) as exc:
results.append({
"requested_username": username,
"checked_at": checked_at,
"check_result": "request_error",
"detail": str(exc),
})
time.sleep(0.5)
with open("profile-check.json", "w", encoding="utf-8") as f:
json.dump(results, f, ensure_ascii=False, indent=2)
print(f"عدد النتائج المحفوظة: {len(results)}")
هذا مثال على التكامل، وليس تقريرًا عن اختبار أُجري بالفعل. يُمرّر المفتاح في المعامل license_key، لكنه لا يُطبع. وقد تتضمن الاستجابة الكاملة معلومات ينبغي تقييد الوصول إليها وفقًا لقواعد فريقك في تخزين البيانات.
كيفية قراءة النتيجة
يعني السجل profile_returned أن النص البرمجي تلقّى كائن JSON باسم ig. قارن requested_username بـ returned_username وراجع المؤشرات المهمة لسير الحملة. على سبيل المثال، يمكن إحالة is_private: true إلى المراجعة اليدوية إذا كانت الحملة تتطلب ملفًا عامًا.

تشير النتائج http_error وrequest_error وunexpected_or_missing_profile_object فقط إلى المرحلة التي لم يحصل فيها النص البرمجي على البنية المتوقعة. وهي لا تثبت أن الحساب محذوف أو خاص أو غير متاح لسبب بعينه. احفظ الاستجابة، وتحقق من الاسم والمفتاح، ثم أعد الطلب أو تواصل مع قنوات الدعم الرسمية للخدمة.
إذا كان أحد الحقول غائبًا، فاتركه مجهولًا؛ ولا تفسّر غيابه على أنه صفر أو false. تعبّر عدّادات الملف الشخصي عن الحالة التي أُعيدت وقت الطلب. وتتيح العلامة الزمنية تمييز هذه اللقطة من نتائج التشغيل التالي.
الأتمتة من دون فقدان قابلية الرصد
انقل التشغيل إلى مجدول مهام أو إلى مرحلة ضمن عملية ETL قائمة. احتفظ بتاريخ الفحص والاسم المطلوب والنتيجة والحالة ومتن الاستجابة. ويمكن في خطوة منفصلة تحميل JSON إلى جدول وإرسال السجلات التي تحتاج إلى مراجعة فقط إلى المختص.
لاكتشاف التغييرات، قارن اللقطات الخاصة بالملف نفسه وفق الحقول المختارة. فالتغير في عدد المنشورات سبب لفتح الملف والتحقق منه، وليس تاريخًا دقيقًا لنشر منشور. كما أن عدد المتابعين قيمة عند لحظة الطلب، لذا يُبنى سجل الملاحظات من اللقطات المحفوظة.
إذا كانت القائمة كبيرة، فاضبط وتيرة الطلبات، وأضف محاولات إعادة محدودة، وسجّل الأخطاء. لا تضع المفتاح في سجلات عناوين URL. ويساعد الفصل بين قائمة الإدخال والنتائج على معرفة الحسابات التي عولجت بالفعل.
النتيجة المتوقعة
ينتج ملف JSON يتضمن نتيجة معالجة كل اسم محدد، وعلامة زمنية، والسمات المتاحة، والاستجابة المحفوظة. وقبل تمرير القائمة إلى الحملة، يمكن تصفية الأسماء المتطابقة والملفات الخاصة والحالات التقنية لإحالتها إلى المراجعة اليدوية. ويحدد الفريق نفسه معايير الخطوة التالية.
المسار والمعاملات موضحة في وثائق IG API؛ وترد معلومات المنتج في صفحة IG Scraper API. ابدأ بعينة صغيرة، وتحقق من الشكل الفعلي للاستجابات، واضبط قواعد التقرير بما يلائم سير عملك.