أتمتة أبحاث السوق الخاصة بك: استخراج بيانات Shopify باستخدام Python

آخر تحديث في April 16, 2026

يُعدّ المسار /products.json في Shopify واحدًا من أكثر الأسرار المكشوفة في عالم بيانات التجارة الإلكترونية. أضِفه إلى أي رابط متجر Shopify، وسيعطيك JSON منظَّمًا مباشرةً — من دون مفاتيح API، ومن دون مصادقة، ومن دون الحاجة إلى تفكيك HTML متداخل ومعقّد.

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

هذا الدليل يغطّي العملية من أولها لآخرها: ما الذي يعيده هذا المسار، وكيف تتنقّل بين آلاف المنتجات، وكيف تتعامل مع حدود المعدّل من دون أن يتم حظرك، وكيف تحوّل JSON المتداخل في Shopify إلى ملف CSV أو Excel نظيف باستخدام pandas. وسأتناول أيضًا المسارات التي لا يتحدث عنها معظم الناس (/collections.json و/meta.json) وأعرض بديلًا بلا أكواد لمن يفضّل الاستغناء عن Python تمامًا.

ما هو مسار Shopify /products.json ولماذا يجعل الاستخراج أسهل؟

كل متجر Shopify يوفّر مسارًا عامًا على {store-url}/products.json يعيد بيانات منتجات منظمة. لا مفاتيح API. لا OAuth. لا أي نوع من المصادقة. كل ما عليك فعله هو إضافة /products.json إلى رابط المتجر، وسيعود لك مصفوفة JSON تحتوي على كل المنتجات الموجودة في الكتالوج.

جرّبه بنفسك الآن: افتح أو في المتصفح. ستجد JSON نظيفًا ومنظّمًا يحتوي على عناوين المنتجات، الأسعار، المتغيرات، الصور، الوسوم — وكل شيء تقريبًا.

قارن ذلك بالبديل: تحليل قوالب HTML الخاصة بـ Shopify، وهي متداخلة جدًا، وغير متسقة من متجر لآخر، وتتغيّر كلما عدّل التاجر القالب. هذا مثال على ما ستتعامل معه:

طريقة HTML (مزعجة):

1<div class="product-card__info">
2  <h3 class="product-card__title">
3    <a href="/products/classic-blue-jeans">Classic Blue Jeans</a>
4  </h3>
5  <span class="price price--on-sale" data-product-price>$149.00</span>
6</div>

طريقة JSON (نظيفة):

1{
2  "title": "Classic Blue Jeans",
3  "handle": "classic-blue-jeans",
4  "vendor": "Hiut Denim",
5  "variants": [{"price": "149.00", "sku": "HD-BLU-32", "available": true}]
6}

JSON يتفوّق من ناحية الاتساق والموثوقية وسهولة التحليل. كما يدعم هذا المسار معامِلَي استعلام مهمين: ?limit= (حتى 250 منتجًا في الصفحة الواحدة، والافتراضي 30) و?page= للتنقل بين الصفحات، وسنستخدمهما كثيرًا في الأمثلة القادمة.

معلومة مهمّة: هذا مسار عام للواجهة الأمامية للمتجر، وليس . يتطلّب Admin API رموز وصول خاصة بمالك المتجر، ويقدّم بيانات الطلبات ومستويات المخزون ومعلومات العملاء. أمّا مسار /products.json العام فهو بيانات منتجات للقراءة فقط يمكن لأي شخص الوصول إليها. سأشرح هذا الفرق بالتفصيل لاحقًا، لأن الالتباس حوله شائع جدًا في المنتديات.

تنبيه: ليس كل متجر Shopify يوفّر هذا المسار. في اختباري، أعادت نحو 71% من المتاجر JSON صالحًا (مثل allbirds.com وgymshark.com وcolourpop.com وkyliecosmetics.com)، بينما تعيد بعض الإعدادات المخصصة خطأ 404 (مثل hiutdenim.co.uk وbombas.com). والفحص السريع بسيط: افتح {store-url}/products.json في المتصفح وانظر إلى النتيجة.

لماذا استخراج Shopify باستخدام Python؟ أهم حالات الاستخدام التجارية

لماذا كل هذا الجهد؟ العائد على الاستثمار. يستخدمون الآن استخراج الأسعار بشكل آلي لأغراض تحليل المنافسة، مقارنةً بـ 34% فقط في عام 2020. كما تُظهر الأبحاث أن . البيانات هنا تساوي مالًا حقيقيًا.

هذه أكثر حالات الاستخدام شيوعًا التي أراها:

حالة الاستخداممن يستفيدما الذي ستحصل عليه
مراقبة أسعار المنافسينفرق عمليات التجارة الإلكترونيةتتبّع تغيّر الأسعار والخصومات وأسعار المقارنة عبر كتالوجات المنافسين
بحث المنتجات والتوريدفرق المشتريات / التسويق التجاريمقارنة خصائص المنتجات والمتغيرات والمواد والتوفر
توليد العملاء المحتملينفرق المبيعاتاستخراج أسماء الموردين وبيانات العلامات التجارية ومعلومات الاتصال من كتالوجات المتاجر
تحليل السوق والفئاتفرق التسويقفهم مزيج المنتجات والوسوم وبنية المجموعات وطريقة التموضع
تتبّع المخزون والتوفرفرق سلسلة الإمدادمراقبة حالة التوفر على مستوى المتغيرات (available: true/false) بمرور الوقت
اكتشاف المنتجات الجديدةفرق المنتجاتتتبّع الطابع الزمني created_at لاكتشاف الإطلاقات الجديدة لدى المنافسين

Python هو الخيار الطبيعي لهذا العمل. يستخدمون Python كلغتهم الأساسية، كما أن منظومته — requests للطلبات، وpandas لمعالجة البيانات، وhttpx للعمل غير المتزامن — تجعل الانتقال من "لديّ رابط" إلى "لديّ جدول بيانات" ممكنًا في أقل من 80 سطرًا من الكود.

مرجع كامل لحقول products.json: شرح كل حقل

معظم الشروحات الأخرى تكتفي بعرض title وid وhandle ثم تنتقل للمثال التالي. لكن استجابة JSON في Shopify تحتوي على أكثر من 40 حقلًا عبر المنتجات والمتغيرات والصور والخيارات. معرفة الحقول المتاحة قبل كتابة الكود توفر عليك إعادة الاستخراج لاحقًا.

استندتُ في هذا المرجع إلى استجابات حية من /products.json تم جلبها في 16 أبريل 2026. والبنية متسقة عبر جميع المتاجر التي تفتح هذا المسار.

الحقول على مستوى المنتج

الحقلنوع البياناتمثالحالة الاستخدام التجارية
idعدد صحيح123456789معرف فريد للمنتج لأغراض إزالة التكرار
titleنص"Classic Blue Jeans"اسم المنتج في الكتالوجات والمقارنات
handleنص"classic-blue-jeans"الجزء النصي من الرابط — يُستخدم لإنشاء روابط صفحات المنتج كالتالي: {store}/products/{handle}
body_htmlنص (HTML) أو null

Our best-selling...

وصف المنتج لتحليل المحتوى وأبحاث SEO
vendorنص"Hiut Denim"اسم العلامة/المورّد للتنقيب عن العملاء أو التوريد
product_typeنص"Jeans"تصنيف الفئة لتحليل السوق
created_atوقت/تاريخ ISO"2024-01-15T10:30:00-05:00"تتبّع وقت إضافة المنتجات (اكتشاف الإطلاقات الجديدة)
updated_atوقت/تاريخ ISO"2025-03-01T08:00:00-05:00"اكتشاف التغييرات الأخيرة في الكتالوج
published_atوقت/تاريخ ISO"2024-01-16T00:00:00-05:00"معرفة متى ظهر المنتج على واجهة المتجر
tagsمصفوفة نصوص["organic", "women", "straight-leg"]تحليل الكلمات المفتاحية/الوسوم لأغراض SEO والتصنيف ورصد الاتجاهات
variantsمصفوفة كائنات(انظر حقول المتغيرات أدناه)السعر وSKU والتوفر لكل متغير
imagesمصفوفة كائنات(انظر حقول الصور أدناه)روابط صور المنتج للكتالوجات والتحليل المرئي
optionsمصفوفة كائنات[{"name": "Size", "values": ["S","M","L"]}]فهم تكوين المنتج (المقاس، اللون، المادة)

الحقول على مستوى المتغير (المتداخلة تحت كل منتج)

الحقلنوع البياناتمثالحالة الاستخدام
idعدد صحيح987654321معرف فريد للمتغير
titleنص"32 / Blue"اسم العرض للمتغير
skuنص"HD-BLU-32"مطابقة SKU مع أنظمة المخزون
priceنص"185.00"مراقبة السعر (ملاحظة: يُعاد كنص، لذا حوّله إلى float عند الحساب)
compare_at_priceنص أو null"200.00"السعر الأصلي — ضروري لتتبع الخصومات
availableقيمة منطقيةtrueتوفر المخزون (المؤشر العام الوحيد للمخزون)
weightعدد عشري1.2تحليل الشحن/اللوجستيات
option1, option2, option3نص"32", "Blue", nullقيم الخيارات الفردية
created_at, updated_atوقت/تاريخ ISOتتبّع التغييرات على مستوى المتغير

الحقول على مستوى الصورة

الحقلنوع البياناتمثالحالة الاستخدام
idعدد صحيح111222333معرف فريد للصورة
srcنص (رابط)"https://cdn.shopify.com/..."رابط مباشر لتنزيل الصورة
altنص أو null"Front view of jeans"النص البديل للصورة لتحليل الإتاحة
positionعدد صحيح1ترتيب الصورة
width, heightعدد صحيح2048, 2048أبعاد الصورة

ما الذي لا يوجد في المسار العام؟

هناك نقطة مهمّة جدًا: inventory_quantity غير متاح في استجابات /products.json العامة. تم حذف هذا الحقل من المسارات العامة في ديسمبر 2017 لأسباب أمنية. المؤشر الوحيد للمخزون الذي ستحصل عليه هو الحقل المنطقي available لكل متغير (true أو false). وللوصول إلى أعداد المخزون الفعلية، تحتاج إلى Admin API الموثّق مع صلاحيات مالك المتجر.

قبل كتابة كود الاستخراج، راجع هذا الجدول وحدد الحقول التي تهمك. إذا كان هدفك مراقبة الأسعار، فستحتاج إلى variants[].price وvariants[].compare_at_price وvariants[].available. وإذا كان هدفك توليد العملاء المحتملين، فركّز على vendor وproduct_type وtags. رشّح البيانات وفقًا لاحتياجك — ستكون ملفات CSV أنظف بكثير.

ما بعد products.json: المجموعات وMeta ومسارات Shopify الأخرى

لا يذكر معظم الشروحات هذه المسارات، لكنها أساسية لعمل استخبارات تنافسية جاد.

/collections.json — كل فئات المتجر

يعيد كل مجموعة (فئة) في المتجر مع العناوين والـ handles والأوصاف وأعداد المنتجات. تحققت من هذا على zoologistperfumes.com وallbirds.com وgymshark.com — وجميعها أعادت JSON صالحًا.

1{
2  "collections": [
3    {
4      "id": 308387348539,
5      "title": "Attars",
6      "handle": "attars",
7      "published_at": "2026-03-29T12:20:32-04:00",
8      "products_count": 1,
9      "image": { "src": "https://cdn.shopify.com/..." }
10    }
11  ]
12}

هل تريد فهم كيفية تنظيم أحد المنافسين لكتالوجه؟ هذا هو المسار المناسب.

/collections/{handle}/products.json — المنتجات حسب الفئة

يعيد المنتجات المفلترة ضمن مجموعة محددة. البنية نفسها الموجودة في /products.json، لكن النطاق يقتصر على فئة واحدة. وهذا مهم جدًا لاستخراج البيانات على مستوى الفئة — مثلًا إذا أردت مراقبة مجموعة "Sale" أو "New Arrivals" لدى منافس.

/meta.json — بيانات وصفية على مستوى المتجر

يعيد اسم المتجر ووصفه والعملة والبلد، والأهم: published_products_count. يتيح لك هذا العدد حساب صفحات الترقيم مسبقًا بدقة: ceil(published_products_count / 250). لم تعد بحاجة إلى زيادة الصفحات عشوائيًا حتى تصل إلى استجابة فارغة.

أي مسار يجب أن تستخدم؟

ما الذي تريدهالمسارهل يحتاج إلى مصادقة؟
كل المنتجات (عام)/products.jsonلا
المنتجات في فئة محددة/collections/{handle}/products.jsonلا
بيانات وصفية للمتجر + عدد المنتجات/meta.jsonلا
كل المجموعات (الفئات)/collections.jsonلا
بيانات الطلبات/المبيعات (لمتجرك فقط)Admin API /orders.jsonنعم (مفتاح API)
كميات المخزون (لمتجرك فقط)Admin API /inventory_levels.jsonنعم

السؤال المتكرر في المنتديات — "هل يمكنني استخراج عدد الوحدات التي باعها المنافس؟" — إجابته المختصرة: لا. ليس من المسارات العامة. بيانات المبيعات وكميات المخزون تتطلب Admin API الموثّق، أي أنك تحتاج إلى صلاحية مالك المتجر. المسارات العامة تعطيك بيانات الكتالوج فقط.

shopify-data-access-methods.webp

كيفية استخراج Shopify باستخدام Python: إعداد خطوة بخطوة

  • مستوى الصعوبة: مبتدئ
  • الوقت المطلوب: حوالي 15 دقيقة (الإعداد + أول عملية استخراج)
  • ما ستحتاجه: Python 3.11+ وpip وطرفية أو Terminal ورابط متجر Shopify تريد استخراجه

الخطوة 1: تثبيت Python والمكتبات المطلوبة

تأكد من تثبيت Python 3.11 أو أحدث (لأن pandas 3.0.x يتطلب ذلك). ثم ثبّت المكتبتين اللتين سنحتاجهما:

1pip install requests pandas

وللتصدير إلى Excel، ستحتاج أيضًا إلى:

1pip install openpyxl

في أعلى الملف البرمجي، أضف هذه الاستيرادات:

1import requests
2import pandas as pd
3import time
4import random
5import json

من المفترض ألا تظهر أخطاء استيراد عند تشغيل السكربت. إذا ألقى pandas خطأً متعلقًا بالإصدار، فحدّث Python إلى 3.12.

الخطوة 2: جلب بيانات المنتجات من /products.json

إليك دالة أساسية تأخذ رابط المتجر، تستدعي المسار، وتعيد JSON محللًا:

1def fetch_products_page(store_url, page=1, limit=250):
2    """Fetch a single page of products from a Shopify store."""
3    url = f"{store_url.rstrip('/')}/products.json"
4    params = {"limit": limit, "page": page}
5    headers = {
6        "User-Agent": "Mozilla/5.0 (compatible; ProductResearch/1.0)"
7    }
8    response = requests.get(url, params=params, headers=headers, timeout=30)
9    response.raise_for_status()
10    return response.json().get("products", [])

تفاصيل مهمّة:

  • limit=250 هو الحد الأقصى الذي يسمح به Shopify لكل صفحة. الافتراضي 30، لذا فإن تعيينه صراحة يقلّل عدد الطلبات الإجمالي حتى 8 مرات.
  • ترويسة User-Agent: استخدم دائمًا قيمة واقعية. الطلبات من دون User-Agent تكون أكثر عرضة لتفعيل أنظمة مكافحة البوتات لدى Shopify.
  • timeout=30: لا تدع طلبًا واحدًا يتجمّد إلى ما لا نهاية.

اختبرها على متجر معروف:

1products = fetch_products_page("https://allbirds.com")
2print(f"Fetched {len(products)} products")
3print(f"First product: {products[0]['title']}")

من المفترض أن ترى شيئًا مثل: Fetched 250 products ثم عنوان أول منتج.

الخطوة 3: التعامل مع الترقيم لاستخراج كل المنتجات

الطلب الواحد يعيد بحد أقصى 250 منتجًا. ومعظم المتاجر تتجاوز هذا العدد (Allbirds لديها أكثر من 1,420 منتجًا). لذلك تحتاج إلى حلقة تمر على الصفحات حتى تصل إلى استجابة فارغة.

1def scrape_all_products(store_url, delay=1.0):
2    """Scrape all products from a Shopify store, handling pagination."""
3    all_products = []
4    page = 1
5    while True:
6        print(f"Fetching page {page}...")
7        products = fetch_products_page(store_url, page=page, limit=250)
8        if not products:
9            print(f"No more products. Total: {len(all_products)}")
10            break
11        all_products.extend(products)
12        print(f"  Got {len(products)} products (total so far: {len(all_products)})")
13        page += 1
14        # كن مهذبًا: انتظر بين الطلبات
15        time.sleep(delay + random.uniform(0, 0.5))
16    return all_products

عندما تعود products فارغة، فهذا يعني أنك وصلت إلى النهاية.

استخدام time.sleep() مع هامش عشوائي صغير يساعدك على البقاء تحت المعدّل غير الرسمي في Shopify (حوالي طلبين في الثانية لكل متجر).

نصيحة احترافية: إذا جلبت /meta.json أولًا، فستعرف بالفعل العدد الكلي للمنتجات ويمكنك حساب عدد الصفحات المطلوبة بدقة: pages = ceil(product_count / 250). بهذه الطريقة تتجنّب إرسال "طلب فارغ إضافي" في النهاية.

الخطوة 4: تحليل الحقول التي تحتاجها

الآن بعد أن أصبحت لديك كل المنتجات في قائمة Python من القواميس، استخرج فقط الحقول التي تهمك. هذا مثال يلتقط أكثر الحقول شيوعًا لمراقبة الأسعار:

1def extract_product_data(products):
2    """Extract key fields from products, flattening variants."""
3    rows = []
4    for product in products:
5        for variant in product.get("variants", []):
6            rows.append({
7                "product_id": product["id"],
8                "title": product["title"],
9                "handle": product["handle"],
10                "vendor": product.get("vendor", ""),
11                "product_type": product.get("product_type", ""),
12                "tags": ", ".join(product.get("tags", [])),
13                "created_at": product.get("created_at", ""),
14                "variant_id": variant["id"],
15                "variant_title": variant.get("title", ""),
16                "sku": variant.get("sku", ""),
17                "price": variant.get("price", ""),
18                "compare_at_price": variant.get("compare_at_price", ""),
19                "available": variant.get("available", ""),
20                "image_url": product["images"][0]["src"] if product.get("images") else ""
21            })
22    return rows

هذا ينشئ صفًا واحدًا لكل متغير — وهو الشكل الأكثر فائدة لمقارنة الأسعار، لأن منتجًا واحدًا مثل "Classic Blue Jeans" قد يحتوي على 12 متغيرًا (6 مقاسات × لونين)، ولكل واحد سعره وحالته الخاصة من حيث التوفر.

تصدير بيانات Shopify المستخرجة إلى CSV وExcel باستخدام pandas

معظم شروحات استخراج Shopify الأخرى تكتفي بحفظ JSON الخام في ملف وتنتهي. هذا مناسب للمطورين، لكنه لا يفيد محلل التجارة الإلكترونية الذي يحتاج جدولًا بحلول يوم الجمعة.

المشكلة أن JSON الخاص بـ Shopify متداخل. يمكن لمنتج واحد أن يحتوي على عشرات المتغيرات، ولكل منها سعر وSKU وتوفر خاص. تحويل ذلك إلى صفوف وأعمدة يتطلب بعض العمل باستخدام pandas.

تحويل JSON المتداخل إلى جدول نظيف

هناك طريقتان، حسب الحاجة:

الخيار A: صف واحد لكل متغير (الأفضل لمراقبة الأسعار وتتبع المخزون)

1# Using the extract_product_data function from Step 4
2products = scrape_all_products("https://allbirds.com")
3rows = extract_product_data(products)
4df = pd.DataFrame(rows)
5print(f"DataFrame shape: {df.shape}")
6print(df.head())

هذا يعطيك جدولًا مسطحًا بحيث يمثّل كل صف تركيبة فريدة من منتج ومتغير. متجر فيه 500 منتج ومتوسط 4 متغيرات لكل منتج سينتج DataFrame بحوالي 2,000 صف.

الخيار B: صف واحد لكل ملخص منتج (الأفضل لعرض الكتالوج)

1def summarize_products(products):
2    """One row per product with min/max price across variants."""
3    rows = []
4    for product in products:
5        prices = [float(v["price"]) for v in product.get("variants", []) if v.get("price")]
6        rows.append({
7            "product_id": product["id"],
8            "title": product["title"],
9            "vendor": product.get("vendor", ""),
10            "product_type": product.get("product_type", ""),
11            "variant_count": len(product.get("variants", [])),
12            "min_price": min(prices) if prices else None,
13            "max_price": max(prices) if prices else None,
14            "any_available": any(v.get("available", False) for v in product.get("variants", [])),
15            "tags": ", ".join(product.get("tags", []))
16        })
17    return rows

التصدير إلى CSV وExcel وGoogle Sheets

1# CSV export (use utf-8-sig so Excel handles special characters)
2df.to_csv("shopify_products.csv", index=False, encoding="utf-8-sig")
3# Excel export (requires openpyxl)
4df.to_excel("shopify_products.xlsx", index=False, engine="openpyxl")
5print("Exported to shopify_products.csv and shopify_products.xlsx")

بالنسبة إلى Google Sheets، يمكنك استخدام مكتبة gspread مع حساب خدمة، لكن بصراحة — في معظم الحالات يكفي التصدير إلى CSV ثم رفع الملف إلى Google Drive، وسيكون الأمر أسرع وأبسط.

استخراج احترافي جاهز للإنتاج: حدود المعدّل، وإعادة المحاولة، وتجنب الحظر

السكربت الأساسي يعمل جيدًا مع المتاجر الصغيرة. لكن ماذا لو كنت تستخرج متجرًا فيه أكثر من 5,000 منتج، أو تتعامل مع عدة متاجر على التوالي؟ هنا تبدأ المشاكل.

فهم حدود المعدّل وسلوك الحظر في Shopify

لا توجد حدود معدل موثقة رسميًا للمسارات العامة في JSON الخاصة بـ Shopify (على عكس نموذج leaky bucket في Admin API)، لكن الاختبار العملي يُظهر ما يلي:

  • المعدل الآمن: نحو 2 طلب في الثانية لكل متجر
  • السقف الناعم: حوالي 40 طلبًا في الدقيقة قبل بدء التقييد
  • HTTP 429: "طلبات كثيرة جدًا" — استجابة الحد الأقصى التقليدية
  • HTTP 430: رمز خاص بـ Shopify يشير إلى حظر أمني (وليس مجرد تقييد معدل)
  • HTTP 403 أو إعادة توجيه إلى CAPTCHA: بعض المتاجر التي تستخدم حماية إضافية مثل Cloudflare

الطلبات القادمة من بنية سحابية مشتركة (AWS Lambda، Google Cloud Run) أكثر عرضة للحظر لأن هذه النطاقات تُستخدم كثيرًا في إساءة الاستخدام.

تقنيات استخراج Shopify بشكل موثوق

هذا هو التسلسل من "يعمل على جهازي" إلى "جاهز للإنتاج":

المستوىالتقنيةالاعتمادية
أساسيrequests.get() + ?page=يتعطّل مع الكتالوجات الكبيرة وقد يتعرض للحظر
متوسطrequests.Session() + ?limit=250 + time.sleep(1) + إعادة المحاولة عند 429يعمل مع معظم المتاجر
متقدمhttpx غير المتزامن + تدوير User-Agent + backoff أسيمناسب للإنتاج، ويتوسع إلى 10 آلاف منتج وأكثر

المستوى المتوسط (الموصى به لمعظم المستخدمين):

1import requests
2from requests.adapters import HTTPAdapter
3from urllib3.util.retry import Retry
4def create_session():
5    """Create a requests session with automatic retry logic."""
6    session = requests.Session()
7    retries = Retry(
8        total=5,
9        backoff_factor=1,  # sleep: 0.5s, 1s, 2s, 4s, 8s
10        status_forcelist=[429, 430, 500, 502, 503, 504],
11        respect_retry_after_header=True
12    )
13    session.mount("https://", HTTPAdapter(max_retries=retries))
14    session.headers.update({
15        "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Safari/537.36"
16    })
17    return session

يتعامل إعداد Retry مع استجابات 429 تلقائيًا باستخدام backoff أسي. أما backoff_factor=1 فيعني أن فترات الانتظار ستكون 0.5 ثانية → 1 ثانية → 2 ثانية → 4 ثوانٍ → 8 ثوانٍ بين المحاولات. كما أن إعادة استخدام الجلسة (requests.Session()) تمنحك أيضًا تجميع الاتصالات، ما يقلل الحمل عند إرسال طلبات متعددة إلى النطاق نفسه.

تدوير User-Agent: إذا كنت تستخرج عدة متاجر، فبدّل بين 3 إلى 5 سلاسل User-Agent واقعية للمتصفحات. الهدف ليس الخداع، بل ألا تبدو كروبوت يرسل نفس الترويسات في كل طلب.

السكربت الكامل الجاهز لاستخراج Shopify مع التصدير إلى CSV

إليك السكربت الكامل الجاهز للنسخ واللصق، ويجمع كل ما سبق. يبلغ طوله نحو 75 سطرًا من الكود الفعلي (إضافةً إلى التعليقات)، وقد اختبرته على Allbirds (1,420 منتجًا) وColourPop (أكثر من 2,000 منتج) وZoologist Perfumes (كتالوج صغير).

1import requests
2import pandas as pd
3import time
4import random
5from requests.adapters import HTTPAdapter
6from urllib3.util.retry import Retry
7def create_session():
8    """Create a session with retry logic for rate limits."""
9    session = requests.Session()
10    retries = Retry(
11        total=5,
12        backoff_factor=1,
13        status_forcelist=[429, 430, 500, 502, 503, 504],
14        respect_retry_after_header=True
15    )
16    session.mount("https://", HTTPAdapter(max_retries=retries))
17    session.headers.update({
18        "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) "
19                      "AppleWebKit/537.36 (KHTML, like Gecko) "
20                      "Chrome/125.0.0.0 Safari/537.36"
21    })
22    return session
23def scrape_shopify(store_url, delay=1.0):
24    """Scrape all products from a Shopify store via /products.json."""
25    session = create_session()
26    all_products = []
27    page = 1
28    base_url = f"{store_url.rstrip('/')}/products.json"
29    while True:
30        print(f"  Page {page}...", end=" ")
31        resp = session.get(base_url, params={"limit": 250, "page": page}, timeout=30)
32        resp.raise_for_status()
33        products = resp.json().get("products", [])
34        if not products:
35            break
36        all_products.extend(products)
37        print(f"{len(products)} products (total: {len(all_products)})")
38        page += 1
39        time.sleep(delay + random.uniform(0, 0.5))
40    return all_products
41def flatten_to_variants(products):
42    """Flatten nested product JSON into one row per variant."""
43    rows = []
44    for p in products:
45        base = {
46            "product_id": p["id"],
47            "title": p["title"],
48            "handle": p["handle"],
49            "vendor": p.get("vendor", ""),
50            "product_type": p.get("product_type", ""),
51            "tags": ", ".join(p.get("tags", [])),
52            "created_at": p.get("created_at", ""),
53            "updated_at": p.get("updated_at", ""),
54            "image_url": p["images"][0]["src"] if p.get("images") else "",
55        }
56        for v in p.get("variants", []):
57            row = {**base}
58            row["variant_id"] = v["id"]
59            row["variant_title"] = v.get("title", "")
60            row["sku"] = v.get("sku", "")
61            row["price"] = v.get("price", "")
62            row["compare_at_price"] = v.get("compare_at_price", "")
63            row["available"] = v.get("available", "")
64            rows.append(row)
65    return rows
66if __name__ == "__main__":
67    STORE_URL = "https://allbirds.com"  # Change this to your target store
68    OUTPUT_CSV = "shopify_products.csv"
69    OUTPUT_EXCEL = "shopify_products.xlsx"
70    print(f"Scraping {STORE_URL}...")
71    products = scrape_shopify(STORE_URL)
72    print(f"\nTotal products scraped: {len(products)}")
73    print("Flattening to variant-level rows...")
74    rows = flatten_to_variants(products)
75    df = pd.DataFrame(rows)
76    print(f"DataFrame: {df.shape[0]} rows x {df.shape[1]} columns")
77    df.to_csv(OUTPUT_CSV, index=False, encoding="utf-8-sig")
78    df.to_excel(OUTPUT_EXCEL, index=False, engine="openpyxl")
79    print(f"\nExported to {OUTPUT_CSV} and {OUTPUT_EXCEL}")

شغّله عبر python scrape_shopify.py. بالنسبة إلى Allbirds، يستغرق ذلك نحو 45 ثانية وينتج ملف CSV يحتوي على أكثر من 5,000 صف تقريبًا (صف واحد لكل متغير). ويبدو الإخراج في الطرفية تقريبًا هكذا:

1Scraping https://allbirds.com...
2  Page 1... 250 products (total: 250)
3  Page 2... 250 products (total: 500)
4  ...
5  Page 6... 170 products (total: 1420)
6Total products scraped: 1420
7Flattening to variant-level rows...
8DataFrame: 5680 rows x 14 columns
9Exported to shopify_products.csv and shopify_products.xlsx

تجاوز Python: استخراج Shopify في نقرتين باستخدام Thunderbit (بديل بلا أكواد)

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

لهذا السبب بنينا — أداة AI لاستخراج الويب تعمل كإضافة على Chrome. من دون كود، ومن دون مفاتيح API، ومن دون إعداد بيئة.

كيف يستخرج Thunderbit متاجر Shopify

يوفّر Thunderbit قالب Shopify Scraper مخصصًا ومُعدًّا مسبقًا لصفحات منتجات Shopify. كل ما عليك هو تثبيت ، ثم الانتقال إلى متجر Shopify والنقر على "Scrape". سيستخرج القالب تلقائيًا أسماء المنتجات والأوصاف والأسعار وتفاصيل المتغيرات والصور ومعلومات البائع.

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

بعض الميزات التي تطابق ما يفعله سكربت Python مباشرة:

  • استخراج الصفحات الفرعية: يزور تلقائيًا كل صفحة تفاصيل منتج ويثري الجدول بالأوصاف الكاملة أو المراجعات أو تفاصيل المتغيرات — وهو ما يحققه سكربت Python لدينا عبر المرور على الصفحات، لكن من دون أي كود.
  • التنقل الآلي بين الصفحات: يتعامل مع الترقيم بالنقر أو التمرير اللانهائي دون أي إعداد.
  • استخراج مجدول: أنشئ مهام متكررة (مثلًا: "كل يوم اثنين الساعة 9 صباحًا") لمراقبة الأسعار بشكل مستمر — من دون cron job أو خادم.
  • تصدير مجاني إلى CSV وExcel وGoogle Sheets وAirtable وNotion في جميع الخطط.

سكربت Python مقابل Thunderbit: مقارنة صريحة

العاملسكربت PythonThunderbit (بلا أكواد)
وقت الإعداد15–60 دقيقة (البيئة + الكود)حوالي دقيقتين (تثبيت إضافة Chrome)
الحاجة إلى البرمجةنعم (Python)لا
التخصيصغير محدودحقول مقترحة بالذكاء الاصطناعي + مطالبات مخصصة
التعامل مع الترقيميجب برمجته يدويًاتلقائي
صيغ التصديرتبرمجها بنفسك (CSV/Excel)CSV وExcel وGoogle Sheets وAirtable وNotion (مجانًا)
التشغيل المجدولCron job + استضافةمجدول مدمج
التعامل مع حدود المعدّليجب برمجة إعادة المحاولة/backoffيتم تلقائيًا
الأفضل لـالمطورين وخطوط البيانات الكبيرةمستخدمي الأعمال، الاستخراج السريع، والمراقبة المتكررة

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

python-vs-thunderbit-comparison.webp

نصائح وأفضل الممارسات لاستخراج متاجر Shopify

تنطبق هذه النصائح بغض النظر عن الأداة التي تختارها:

  • استخدم دائمًا ?limit=250 لتقليل عدد الطلبات. الافتراضي 30 لكل صفحة يعني 8 أضعاف عدد الطلبات للحصول على نفس البيانات.
  • احترم المتجر: أضف تأخيرًا بين 1 و2 ثانية بين الطلبات. إغراق الخادم بطلبات سريعة ممارسة سيئة ويزيد احتمال حظرك.
  • افحص robots.txt أولًا: الملف الافتراضي في Shopify لا يحظر /products.json. لكن بعض المتاجر تضيف قواعد مخصصة، لذا تحقّق قبل الاستخراج على نطاق واسع.
  • احفظ JSON الخام محليًا أولًا ثم عالجه لاحقًا. إذا تغيّر منطق التحليل لديك لاحقًا، فلن تحتاج إلى إعادة الاستخراج. مجرد json.dump(all_products, open("raw_data.json", "w")) قبل التسطيح قد يوفر عليك الكثير.
  • أزل التكرارات باستخدام product.id: أحيانًا تعيد حواف الترقيم منتجات مكررة عند حدود الصفحات. استخدام df.drop_duplicates(subset=["product_id", "variant_id"]) يحل ذلك بسرعة.
  • حوّل price إلى float قبل إجراء العمليات الحسابية. Shopify يعيد الأسعار كنصوص ("185.00") وليس كأرقام.
  • راقب تغييرات المسار: رغم أن /products.json كان مستقرًا لسنوات، إلا أن Shopify قد يقيّده نظريًا. إذا بدأ المستخرج فجأة بإرجاع 404، فتحقق يدويًا من المتجر أولًا.

لمعرفة المزيد عن بناء أدوات استخراج متينة، راجع دليلنا حول .

الاعتبارات القانونية والأخلاقية عند استخراج Shopify

قسم مختصر، لكنه مهم.

يعرض المسار /products.json بيانات منتجات متاحة للعامة — وهي نفسها المعلومات التي يراها أي زائر أثناء تصفح المتجر. تتضمن شروط خدمة Shopify نصًا حول عدم استخدام "وسائل آلية" للوصول إلى "الخدمات"، لكن المقصود هنا هو المنصة نفسها (لوحة الإدارة، الدفع)، وليس بيانات الواجهة العامة للمتجر. وحتى أبريل 2026، لم تُرفع دعاوى معروفة تخص استخراج بيانات Shopify العامة تحديدًا.

هناك سوابق قانونية تدعم استخراج البيانات العامة: قضية hiQ v. LinkedIn أكدت أن استخراج البيانات المتاحة للعامة لا يخرق CFAA، كما أن حكم Meta v. Bright Data (2024) قضى بأن قيود شروط الاستخدام تنطبق فقط عندما يكون المستخدم مسجّل الدخول.

أفضل الممارسات:

  • استخرج فقط بيانات المنتجات المتاحة للعامة
  • لا تستخرج البيانات الشخصية أو بيانات العملاء
  • احترم robots.txt وحدود المعدّل
  • التزم بـ GDPR/CCPA إذا كنت تتعامل مع أي بيانات شخصية (بيانات كتالوج المنتجات ليست شخصية)
  • عرّف بنفسك عبر User-Agent واضح
  • استخراج متجر Shopify الخاص بك عبر Admin API أمر مسموح دائمًا

ولمزيد من التعمّق، راجع مقالتنا حول .

الخلاصة وأهم النقاط

يجعل المسار العام /products.json في Shopify استخراج بيانات التجارة الإلكترونية أمرًا سهلًا جدًا. سير العمل هو: أضف /products.json → اجلب البيانات باستخدام Python → تنقّل بين الصفحات باستخدام ?limit=250&page= → حوّلها إلى شكل مسطّح باستخدام pandas → صدّر إلى CSV أو Excel.

ما الذي يقدمه هذا الدليل ولا يقدمه غيره:

  • مرجع كامل للحقول: تعرف بالضبط ما البيانات المتاحة (أكثر من 40 حقلًا عبر المنتجات والمتغيرات والصور) قبل كتابة أول سطر كود
  • مسارات إضافية: /collections.json و/meta.json يمنحانك معلومات على مستوى الفئات وبيانات وصفية للمتجر لا تغطيها الشروحات الأخرى
  • تقنيات جاهزة للإنتاج: إعادة استخدام الجلسة، وbackoff الأسي، وترويسات User-Agent، و?limit=250 للتعامل مع حدود المعدّل الواقعية
  • تصدير صحيح إلى CSV/Excel: بيانات مسطحة على مستوى المتغير باستخدام pandas، وليس مجرد حفظ JSON خام
  • بديل بلا أكواد: لمن يفضّل السرعة على مرونة الكود

إذا كنت تحتاج إلى سحب بيانات Shopify مرة واحدة أو بشكل متكرر من دون كود، فجرب — فقالب Shopify Scraper يتكفل بكل شيء من الترقيم إلى التصدير. أما إذا كنت تبني خطوط بيانات مخصصة أو تستخرج على نطاق واسع عبر عدة متاجر، فإن سكربت Python في هذا الدليل يمنحك تحكمًا كاملًا.

اطّلع على لمشاهدة شروحات مرئية، أو استكشف أدلتنا حول و للحصول على تقنيات ذات صلة.

جرّب Thunderbit لاستخراج Shopify

الأسئلة الشائعة

هل يمكن استخراج أي متجر Shopify باستخدام products.json؟

معظم متاجر Shopify تفتح هذا المسار افتراضيًا — وفي الاختبارات أعاد نحو 71% منها JSON صالحًا. بعض المتاجر التي تستخدم إعدادات مخصصة أو طبقات حماية إضافية (مثل Cloudflare أو إعدادات headless) قد تعيد 404 أو تحظر الطلب. الفحص السريع: افتح {store-url}/products.json في المتصفح. إذا ظهر JSON، فأنت جاهز.

هل من القانوني استخراج بيانات متاجر Shopify؟

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

كم عدد المنتجات التي يمكن استخراجها من متجر Shopify؟

لا يوجد حد صارم لعدد المنتجات الكلي. يتيح لك الترقيم باستخدام ?limit=250&page= جلب الكتالوج بالكامل. بالنسبة للمتاجر الضخمة جدًا (25,000+ منتج)، استخدم إعادة استخدام الجلسة والتأخير لتجنب حدود المعدّل. ويمكن لمسار /meta.json أن يخبرك بعدد المنتجات بدقة مسبقًا، حتى تعرف عدد الصفحات المتوقع.

ما الفرق بين products.json وShopify Admin API؟

/products.json هو مسار عام — من دون مصادقة، ويعرض بيانات المنتجات للقراءة فقط، ويمكن لأي شخص الوصول إليه. أما Admin API فيتطلب رموز وصول خاصة بمالك المتجر، ويقدّم الطلبات وكميات المخزون وبيانات العملاء وصلاحيات الكتابة. إذا كنت تحتاج إلى بيانات المبيعات أو كميات المخزون الفعلية، فستحتاج إلى الوصول إلى Admin API (أي يجب أن تكون مالك المتجر أو لديك إذنه).

هل يمكنني استخراج Shopify من دون Python؟

بالتأكيد. أدوات مثل تتيح لك استخراج متاجر Shopify من خلال إضافة Chrome من دون أي كود. فهي تتعامل مع الترقيم تلقائيًا وتصدّر مباشرة إلى CSV أو Excel أو Google Sheets أو Airtable أو Notion. وبالنسبة للمطورين الذين يفضّلون لغات أخرى، فإن مسار /products.json نفسه يعمل مع JavaScript وRuby وGo — أي لغة يمكنها تنفيذ طلبات HTTP وتحليل JSON.

معرفة المزيد

جدول المحتويات

جرّب Thunderbit

اسحب العملاء المحتملين وبيانات أخرى في نقرتين فقط. مدعوم بالذكاء الاصطناعي.

احصل على Thunderbit مجاني
استخرج البيانات باستخدام الذكاء الاصطناعي
انقل البيانات بسهولة إلى Google Sheets أو Airtable أو Notion
Chrome Store Rating
PRODUCT HUNT#1 Product of the Week