قبل بضعة أشهر، ورّاني أحد مهندسينا سكربت Python كتبه خلال الويكند. كان هدفه يسحب صور الإلهام الخاصة بالمنتجات من Pinterest لمشروع أبحاث سوق. شغّله، وكانت النتيجة… 16 Pin فقط. من لوحة فيها أكثر من 2,000. ظل يطالع الشاشة ثم يطالعني، وقال: "أعتقد أن Pinterest يسخر مني".
وهو مو الوحيد. بصراحة، هذه أكثر مشكلة أشوفها عند المطورين اللي يحاولون استخراج بيانات Pinterest باستخدام Python. تفتح requests وBeautifulSoup، تزور رابط Pinterest، ثم تطلع لك كم قطعة بسيطة أو صفحة HTML فاضية. السبب؟ Pinterest عبارة عن تطبيق أحادي الصفحة مبني بالكامل على JavaScript — يعني طلب HTTP الثابت ما يشوف المحتوى الحقيقي أبدًا. في هذا الدليل، بشرح لك ليه يصير كذا، وما هي الطرق اللي تشتغل فعلًا (Playwright، واعتراض الـ API الداخلي، وأدوات بدون كود مثل Thunderbit)، وبعطيك أمثلة عملية خطوة بخطوة لاستخراج الـ Pins واللوحات (Boards) وملفات المستخدمين، والتعامل مع التمرير اللانهائي، والحصول على الصور عالية الدقة. سواء كنت تبغى تبني أداة استخراج احترافية أو بس تجمع البيانات بسرعة، فهذا المقال بيفيدك.
ما المقصود باستخراج بيانات Pinterest؟
استخراج بيانات Pinterest يعني جمع البيانات من Pinterest برمجيًا — مثل صور الـ Pin والعناوين والوصف وأسماء اللوحات وعدد المتابعين والروابط. بدل ما تتصفح يدويًا وتحفظ كل Pin لحاله، تقدر تستخدم كود (أو أداة) لجمع بيانات منظمة من نتائج البحث أو اللوحات أو ملفات المستخدمين على نطاق واسع.
ومع وجود أكثر من 240 مليار Pin على المنصة و619 مليون مستخدم نشط شهريًا حتى أواخر 2025، يعتبر Pinterest واحدًا من أغنى مصادر البيانات البصرية على الويب. وللشركات، هذي البيانات كنز حقيقي — سواء كنت تتابع اتجاهات المنتجات، أو تقارن محتوى المنافسين، أو تبني قوائم للتواصل مع المؤثرين.
لماذا نستخدم Python لاستخراج بيانات Pinterest؟
Pinterest ما عاد مجرد لوحة إلهام لمخططي حفلات الزفاف. صار منصة قوية لذكاء الأعمال — إذ إن 85% من مستخدمي Pinterest الأسبوعيين اشتروا شيئًا بناءً على Pins من العلامات التجارية، كما أن 96–97% من أهم عمليات البحث غير مرتبطة بعلامات تجارية، وهذا يعني أن المستخدمين يدخلون بنية شراء لكن بدون ولاء مسبق لعلامة معينة. وهذي فرصة كبيرة للاكتشاف — وتوضح ليه فرق كثيرة تبغى بيانات Pinterest بشكل منظم.
وهذا ينعكس عمليًا كالتالي بحسب الفريق:
| الفريق | البيانات المطلوبة | القيمة التجارية |
|---|---|---|
| عمليات التجارة الإلكترونية | صور المنتجات، الأسعار، الجماليات الرائجة | تسعير تنافسي، ومخزون مرتبط بالاتجاهات |
| التسويق | أداء اللوحات، تفاعل الـ Pin، محتوى المنافسين | استراتيجية المحتوى، وقياس أداء الحملات |
| المبيعات / توليد العملاء | ملفات المبدعين، عدد المتابعين، معلومات التواصل | التواصل مع المؤثرين، واستهداف الشراكات |
| العقارات | Pins تنسيق المنازل، اتجاهات الديكور، تخطيطات الغرف | تصوير القوائم، وإرشادات التنسيق الداخلي |
| صناع المحتوى | المواضيع الرائجة، التنسيقات الشائعة، المواسم | تقويم المحتوى، ودراسة الأسلوب البصري |
والنقطة الأهم: الـ API الرسمي لـ Pinterest محدود. فهو يحتاج حساب أعمال، وموافقة مسبقة (بما فيها عرض فيديو لتطبيقك)، وكمان يعطيك فقط وصولًا لبيانات حسابك أنت. إذا كنت تبغى تتصفح اللوحات العامة أو نتائج البحث أو ملفات المنافسين، فالاستخراج هو البديل العملي. ولهذا تلجأ فرق كثيرة إلى Python — أو إلى أدوات بدون كود مثل Thunderbit عندما تبغى النتائج بدون إعدادات معقدة.
لماذا يفشل BeautifulSoup وحده مع Pinterest، وما الذي يعمل فعلًا؟
إذا حاولت استخراج بيانات Pinterest باستخدام requests + BeautifulSoup وحصلت على 16 عنصرًا فقط أو صفحة فاضية، فأنت مو متخيل. Pinterest مبني باستخدام React ويعرض 100% من المحتوى عبر JavaScript. ولما تطلب رابط Pinterest عبر HTTP عادي، السيرفر يرسل لك HTML بسيط جدًا — بعض وسوم <link> و<script>، و<div> فاضي يركّب فيه React التطبيق. كل بطاقات الـ Pin والصور والعناوين والشبكات تُضاف بعد تنفيذ JavaScript داخل المتصفح.
ما فيه تنفيذ JavaScript = ما فيه Pins.
طيب وش اللي ينجح؟ هذه مقارنة سريعة بين الطرق الرئيسية:
| الطريقة | تدعم JavaScript؟ | تحصل على كل البيانات؟ | مستوى التعقيد | الأنسب لـ |
|---|---|---|---|---|
requests + BeautifulSoup | لا | تقريبًا 0–16 عنصرًا | منخفض | غير مناسبة لـ Pinterest |
| Selenium / Playwright | نعم | نعم، مع منطق للتمرير | متوسط | تحكم كامل، وسلاسل عمل Python |
| اعتراض الـ API الداخلي لـ Pinterest | نعم | نعم، بيانات JSON مقسمة على صفحات | مرتفع | أقصى قدر من البيانات، من دون متصفح |
| Scraper API من طرف ثالث | نعم | يختلف | منخفض | التوسع من دون بنية تحتية |
| أداة بدون كود (Thunderbit) | نعم | بيانات منظمة بالذكاء الاصطناعي | منخفض جدًا | لغير التقنيين، ونتائج سريعة |
في هذا الدليل، أنصح باستخدام Playwright كخيار Python. هو يعرض JavaScript، ويدعم محاكاة التمرير، وصيانته ممتازة (أكثر من 78,600 نجمة على GitHub، ونمو 180% سنويًا في الوظائف المطلوبة)، وكمان أسرع من Selenium بنسبة 35–45% في الاختبارات. وإذا كنت تفضل الشغل بدون كود، فبغطي هذا الخيار أيضًا.
Pinterest API الرسمي مقابل Python Scraping مقابل الأدوات بدون كود: أي مسار تختار؟
قبل ما تبدأ تكتب الكود، من المفيد تسأل نفسك: هل فعلًا تحتاج هذا المسار؟ هذا إطار قرار سريع:
| المعيار | Pinterest API | استخراج البيانات بـ Python | Thunderbit (بدون كود) |
|---|---|---|---|
| يتطلب موافقة | حساب أعمال + عرض فيديو | لا | لا |
| الوصول إلى Pins/Boards العامة | محدود (بياناتك فقط) | كامل | كامل |
| تنزيل الصور بدقة كاملة | يختلف | نعم، عبر تحليل الرابط | نعم، عبر استخراج الصور |
| التعامل مع التمرير اللانهائي | غير قابل للتطبيق | نعم، عبر الكود | تلقائي |
| الحاجة للصيانة | منخفضة | مرتفعة (قد تتغير المحددات) | لا توجد (الذكاء الاصطناعي يتكيف) |
| التصدير إلى Sheets/Airtable | يدوي | عبر كود مخصص | مدمج |
| وقت الإعداد | ساعات–أيام | 30–60 دقيقة | دقيقتان |
إذا كنت مسوقًا، أو مسؤول عمليات تجارة إلكترونية، أو أي شخص يبغى بيانات Pinterest في جدول بيانات بدون كتابة أو صيانة سكربتات Python، فإن Thunderbit AI Web Scraper هو الطريق الأسرع. تفتح أي صفحة على Pinterest، تضغط "AI Suggest Fields"، ثم "Scrape"، وبعدها تصدّر مباشرة إلى Google Sheets أو Excel أو Airtable أو Notion. وحتى ميزة استخراج الصفحات الفرعية تقدر تتبع روابط الـ Pin الفردية لإغناء البيانات تلقائيًا. شفت أعضاء فرق ما كتبوا ولا سطر كود يجمعون أكثر من 500 Pin إلى Google Sheet في أقل من ثلاث دقائق.
أما إذا كنت تبغى تحكم كامل، أو ناوي تدمج الاستخراج داخل pipeline بـ Python، أو ببساطة تحب تبني الأدوات بنفسك — فكمّل القراءة.
إعداد بيئة Python لاستخراج بيانات Pinterest
- مستوى الصعوبة: متوسط
- الوقت المطلوب: حوالي 30–60 دقيقة (بما في ذلك البرمجة والاختبار)
- ما تحتاجه: Python 3.9+، ومتصفح Chrome (للاختبار)، والوصول إلى الطرفية/سطر الأوامر
تثبيت Playwright والاعتماديات
ابدأ بإنشاء مجلد للمشروع وإعداد بيئة افتراضية:
mkdir pinterest-scraper
cd pinterest-scraper
python -m venv venv
source venv/bin/activate # على Windows: venv\Scripts\activate
بعدها ثبّت Playwright وحمّل نسخة Chromium:
pip install playwright
playwright install chromium
كمان راح تستخدم وحدات Python المدمجة json وos وcsv لتصدير البيانات. ما تحتاج تثبيت إضافي لها.
هيكل مجلد المشروع
أنصح ترتب الملفات من البداية:
pinterest-scraper/
├── scraper.py
├── config.py
├── output/
│ ├── pins.json
│ └── pins.csv
└── images/
├── board-name-1/
└── board-name-2/
في ملف config.py، عيّن سلسلة user agent الخاصة بك. Pinterest يحظر بصمات المتصفحات headless الافتراضية، لذلك استخدم سلسلة واقعية:
USER_AGENT = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/133.0.0.0 Safari/537.36"
الخطوة 1: إنشاء رابط البحث في Pinterest
أنشئ رابط البحث بإدراج عبارة البحث داخل القالب:
query = "mid century modern furniture"
url = f"https://www.pinterest.com/search/pins/?q={query.replace(' ', '%20')}&rs=typed"
تقدر تخليها ديناميكية لأي عبارة بحث. المعامل rs=typed يخبر Pinterest أن الاستعلام كُتب يدويًا (وليس اقتراحًا)، وهذا أحيانًا يؤثر في صلة النتائج.
الخطوة 2: تشغيل متصفح Headless وتحميل الصفحة
هذا هو الإعداد الأساسي لـ Playwright. لاحظ user agent المخصص — بدونه، غالبًا Pinterest يحظر الطلب أو يوديك لصفحة تسجيل دخول.
import asyncio
from playwright.async_api import async_playwright
from config import USER_AGENT
async def scrape_search(query, max_pins=100):
url = f"https://www.pinterest.com/search/pins/?q={query.replace(' ', '%20')}&rs=typed"
async with async_playwright() as p:
browser = await p.chromium.launch(headless=True)
page = await browser.new_page(
user_agent=USER_AGENT,
viewport={"width": 1920, "height": 1080}
)
await page.goto(url)
await asyncio.sleep(3) # انتظار تحميل JavaScript للـ Pins الأولية
بعد تنفيذ هذا الجزء، يفترض أن الصفحة حمّلت أول دفعة من الـ Pins — غالبًا بين 25 و50.
الخطوة 3: استخراج بيانات الـ Pin من الصفحة
Pinterest يحط كل Pin داخل div يحمل data-test-id='pinWrapper'. داخلها بتلقى رابطًا (<a>) فيه عنوان الـ Pin ورابطه (عبر aria-label)، وعنصر <img> يحمل رابط الصورة المصغرة.
results = []
pins = await page.query_selector_all("div[data-test-id='pinWrapper']")
for pin in pins:
link = await pin.query_selector("a")
if not link:
continue
title = await link.get_attribute("aria-label") or ""
href = await link.get_attribute("href") or ""
img = await pin.query_selector("img")
src = await img.get_attribute("src") if img else ""
results.append({
"title": title,
"url": f"https://www.pinterest.com{href}" if href.startswith("/") else href,
"image_url": src
})
بهذه المرحلة، results يحتوي على الـ Pins الظاهرة في الجزء الأول من الشاشة. وللحصول على المزيد، تحتاج تمرير — وهذا يودينا لأهم جزء.
الخطوة 4: حفظ النتائج بصيغة JSON أو CSV
بعد الاستخراج، احفظ البيانات في ملفات يسهل استخدامها لاحقًا:
import json
import csv
def save_json(data, filepath="output/pins.json"):
with open(filepath, "w", encoding="utf-8") as f:
json.dump(data, f, ensure_ascii=False, indent=2)
def save_csv(data, filepath="output/pins.csv"):
if not data:
return
with open(filepath, "w", newline="", encoding="utf-8-sig") as f:
writer = csv.DictWriter(f, fieldnames=data[0].keys())
writer.writeheader()
writer.writerows(data)
استخدم ترميز utf-8-sig لملف CSV إذا كنت بتفتحه في Excel — لأنه يمنع ظهور الأحرف بشكل مشوّه.
استخراج لوحات Pinterest الكاملة وملفات المستخدمين
هذه فجوة كبيرة في المحتوى الموجود حاليًا. ما لقيت دليل منافس واحد يشرح استخراج اللوحات أو الملفات الشخصية بعمق — رغم أنها من أكثر الميزات المطلوبة في المنتديات. الناس تبغى تنزل كل Pins من لوحة معينة، وتنظم الصور في مجلدات مستقلة لكل لوحة، وتستخرج بيانات على مستوى الملف الشخصي مثل عدد المتابعين وقائمة اللوحات.
استخراج كل Pins من رابط لوحة
روابط اللوحات عادة تكون بالشكل https://www.pinterest.com/{username}/{board-name}/. وبنية الصفحة تشبه نتائج البحث — حيث تُلفّ الـ Pins داخل div[data-test-id='pinWrapper'] — لكن لازم تمرر لتحميلها كلها.
async def scrape_board(board_url, max_pins=500):
async with async_playwright() as p:
browser = await p.chromium.launch(headless=True)
page = await browser.new_page(user_agent=USER_AGENT, viewport={"width": 1920, "height": 1080})
await page.goto(board_url)
await asyncio.sleep(3)
seen_ids = set()
all_pins = []
for scroll_round in range(100): # حد أمان
pins = await page.query_selector_all("div[data-test-id='pinWrapper']")
new_count = 0
for pin in pins:
link = await pin.query_selector("a")
if not link:
continue
href = await link.get_attribute("href") or ""
if href in seen_ids:
continue
seen_ids.add(href)
new_count += 1
title = await link.get_attribute("aria-label") or ""
img = await link.query_selector("img")
src = await img.get_attribute("src") if img else ""
all_pins.append({
"title": title,
"url": f"https://www.pinterest.com{href}" if href.startswith("/") else href,
"image_url": src
})
print(f"التمرير {scroll_round + 1}: تم جمع {len(all_pins)} Pin فريد")
if new_count == 0 or len(all_pins) >= max_pins:
break
prev_height = await page.evaluate("document.body.scrollHeight")
await page.evaluate("window.scrollTo(0, document.body.scrollHeight)")
await asyncio.sleep(2.5)
curr_height = await page.evaluate("document.body.scrollHeight")
if curr_height == prev_height:
break # لا يوجد محتوى إضافي
await browser.close()
return all_pins
انتبه لشيء مهم: أحيانًا تعرض صفحات اللوحات تبويبًا اسمه "More Ideas" يفصل بين الـ Pins المحفوظة والاقتراحات الخوارزمية. إذا كنت تبغى فقط الـ Pins المحفوظة الخاصة بالمستخدم، فتوقف عن التمرير لما يظهر هذا الفاصل.
استخراج ملف مستخدم: اللوحات، وعدد المتابعين، والـ Pins
روابط الملفات الشخصية تكون مثل https://www.pinterest.com/{username}/. ومن صفحة الملف الشخصي تقدر تستخرج:
- عدد المتابعين/المتابَعين: ابحث عن
div[data-test-id='follower-count'] - قائمة اللوحات: كل لوحة تكون بطاقة ترتبط بـ
/{username}/{board-name}/ - إجمالي عدد الـ Pins: يظهر أحيانًا في رأس الملف الشخصي
async def scrape_profile(username):
url = f"https://www.pinterest.com/{username}/"
async with async_playwright() as p:
browser = await p.chromium.launch(headless=True)
page = await browser.new_page(user_agent=USER_AGENT, viewport={"width": 1920, "height": 1080})
await page.goto(url)
await asyncio.sleep(3)
# استخراج عدد المتابعين
follower_el = await page.query_selector("div[data-test-id='follower-count']")
followers = await follower_el.inner_text() if follower_el else "غير متاح"
# استخراج روابط اللوحات
board_links = await page.query_selector_all("a[href*='/" + username + "/']")
boards = []
for bl in board_links:
href = await bl.get_attribute("href") or ""
name = await bl.get_attribute("aria-label") or href.split("/")[-2]
if href.count("/") >= 3 and href != f"/{username}/":
boards.append({"name": name, "url": f"https://www.pinterest.com{href}"})
await browser.close()
return {"username": username, "followers": followers, "boards": boards}
ولجمع كل الـ Pins عبر جميع لوحات الملف الشخصي، كرر على قائمة اللوحات واستدعِ scrape_board() لكل لوحة. وتقدر أيضًا ترتب الصور التي تم تنزيلها داخل مجلدات منفصلة لكل لوحة تلقائيًا.
بناء معالج تمرير لانهائي جاهز للإنتاج
هذه هي النقطة اللي تفرق بين أداة بسيطة ومُستخرِج حقيقي. أكبر مشكلة — وشفتها في أكثر من اثني عشر نقاشًا في المنتديات — هي أن أدوات الاستخراج ما ترجع إلا 16–25 عنصرًا لأنها ما تتمرر بما يكفي، أو لأنها تستخدم عدد تمريرات ثابت مثل for i in range(5): scroll() وتنتظر الأفضل.
هذا الأسلوب غير موثوق. Pinterest يحمّل المحتوى الجديد على دفعات تقارب 25 Pin، ويبدأ هذا عند التمرير. إذا مررت خمس مرات، ممكن تحصل على 125 Pin — أو 75 إذا كان الاتصال بطيئًا، أو 150 إذا كانت الدفعات أصغر. تحتاج نمط أذكى.
نمط التمرير حتى لا يظهر محتوى جديد
هذه دالة تمرير قوية تتتبع معرفات الـ Pin الفريدة، وتستخدم مهلة قابلة للتعديل، وتضم منطق إعادة المحاولة، وتطبع التقدم:
import time
import random
async def scroll_and_collect(page, max_pins=1000, max_scrolls=200, scroll_pause=2.5):
seen_ids = set()
all_pins = []
no_new_count = 0
for i in range(max_scrolls):
pins = await page.query_selector_all("div[data-test-id='pinWrapper']")
new_this_round = 0
for pin in pins:
link = await pin.query_selector("a")
if not link:
continue
href = await link.get_attribute("href") or ""
if href in seen_ids:
continue
seen_ids.add(href)
new_this_round += 1
title = await link.get_attribute("aria-label") or ""
img = await pin.query_selector("img")
src = await img.get_attribute("src") if img else ""
all_pins.append({
"title": title,
"url": f"https://www.pinterest.com{href}" if href.startswith("/") else href,
"image_url": src
})
print(f" التمرير {i+1}: {new_this_round} Pin جديد | {len(all_pins)} Pin فريد إجمالًا")
if len(all_pins) >= max_pins:
print(f" تم الوصول إلى حد max_pins ({max_pins}). التوقف.")
break
if new_this_round == 0:
no_new_count += 1
if no_new_count >= 3:
print(" ما ظهر أي محتوى جديد بعد 3 تمريرات متتالية. انتهى المحتوى.")
break
else:
no_new_count = 0
prev_height = await page.evaluate("document.body.scrollHeight")
await page.evaluate("window.scrollTo(0, document.body.scrollHeight)")
await asyncio.sleep(scroll_pause + random.uniform(0.5, 1.5))
curr_height = await page.evaluate("document.body.scrollHeight")
if curr_height == prev_height and new_this_round == 0:
print(" ارتفاع الصفحة ما تغير وما ظهرت Pins جديدة. غالبًا انتهت الخلاصة.")
break
return all_pins
ليش هذا التصميم فعّال؟
- إزالة التكرار عبر href: رابط كل Pin فريد، لذلك نستخدمه كمعرّف. هذا يمنع عدّ الـ Pin نفسه مرتين لما يعاد رسم DOM أثناء التمرير.
- قاعدة ثلاث مرات: إذا ما ظهر أي محتوى جديد في ثلاث تمريرات متتالية، نتوقف. هذا يعالج حالة أن الصفحة ما زالت تحمل لكن ما فيها محتوى جديد.
- تذبذب عشوائي في التوقف: إضافة تأخير عشوائي بين 0.5 و1.5 ثانية بين التمريرات يجعل السلوك أقرب للبشري ويقلل احتمال تفعيل أنظمة مكافحة البوت.
- حد أمان لعدد التمريرات: يمنع الدخول في حلقات لا نهائية إذا صار خطأ ما.
التعامل مع الحالات الخاصة
- فاصل "More Ideas": في صفحات اللوحات، يضيف Pinterest أحيانًا قسمًا باسم "More Ideas". إذا كنت تبغى فقط الـ Pins الأصلية المحفوظة في اللوحة، تقدر تتحقق من هذا العنصر وتتوقف لما يظهر.
- تحديد المعدل في الجلسات الطويلة: إذا كنت تتمرر عبر لوحة فيها آلاف الـ Pins، قد يبدأ Pinterest يخفف الاستجابات. إذا لاحظت أن بعض التمريرات ما تُظهر محتوى جديد بشكل متقطع (وليس ثلاث مرات متتالية)، فزد مدة التوقف إلى 5 ثوانٍ أو أكثر.
الحصول على صور Pinterest عالية الدقة، وليس الصور المصغرة
هذه النقطة تزعج كثيرين. تطلع بمجموعة Pins، وتنزّل الصور، فتجدها كلها صورًا مصغرة صغيرة بعرض 236 بكسل. والناس في المنتديات يصفونها بأنها "جودة سيئة جدًا، وكأن الحجم صغير للغاية". الحل هو فهم بنية روابط صور Pinterest.
فهم مسارات روابط صور Pinterest
كل صور Pinterest تُقدَّم من https://i.pinimg.com/{size}/{hash}.jpg. الجزء {size} هو اللي يحدد الدقة:
| مسار الحجم | الأبعاد | الاستخدام |
|---|---|---|
/236x/ | بعرض 236 بكسل | عرض الشبكة الافتراضي (ما تحصل عليه عادةً) |
/474x/ | بعرض 474 بكسل | دقة متوسطة |
/736x/ | بعرض 736 بكسل | عرض تفاصيل الـ Pin / العرض الموسع |
/originals/ | أبعاد الرفع الأصلية | الدقة الكاملة |
دالة مساعدة: ترقية أي رابط صورة من Pinterest إلى أعلى دقة
هذه دالة تعيد كتابة أي رابط صورة من Pinterest إلى أعلى جودة متاحة، مع منطق بديل تلقائي:
import requests as req
def upgrade_image_url(url, preferred_size="originals"):
"""إعادة كتابة رابط صورة Pinterest إلى أعلى دقة متاحة."""
sizes = ["originals", "736x", "474x", "236x"]
if preferred_size not in sizes:
preferred_size = "originals"
for size in sizes[sizes.index(preferred_size):]:
upgraded = url
for s in sizes:
upgraded = upgraded.replace(f"/{s}/", f"/{size}/")
try:
resp = req.head(upgraded, timeout=5, allow_redirects=True)
if resp.status_code == 200:
return upgraded
except Exception:
continue
return url # إرجاع الرابط الأصلي إذا فشلت كل المحاولات
ملاحظة مهمة (حتى 2025): مسار /originals/ صار يرجع كثيرًا أخطاء HTTP 403 Forbidden. وهذا مؤكد في مشكلة موثقة في gallery-dl حتى منتصف 2025. الحد الأعلى الموثوق هو /736x/. دالتي تحاول /originals/ أولًا، ثم تنتقل تلقائيًا إلى /736x/.
تنزيل الصور في مجلدات منظمة
import os
import time
def download_images(pins, folder="images/default", delay=1.5):
os.makedirs(folder, exist_ok=True)
for i, pin in enumerate(pins):
img_url = upgrade_image_url(pin.get("image_url", ""), preferred_size="736x")
if not img_url:
continue
filename = f"pin_{i+1}.jpg"
filepath = os.path.join(folder, filename)
try:
resp = req.get(img_url, timeout=15)
if resp.status_code == 200:
with open(filepath, "wb") as f:
f.write(resp.content)
print(f" تم تنزيل {filename} ({len(resp.content) // 1024} KB)")
else:
print(f" فشل {filename}: HTTP {resp.status_code}")
except Exception as e:
print(f" خطأ أثناء تنزيل {filename}: {e}")
time.sleep(delay + random.uniform(0.3, 0.8))
حط تأخير بين عمليات التنزيل. أنا عادة أستخدم 1.5–2.3 ثانية مع تذبذب بسيط. بدون هذا، ممكن Pinterest يحظر عنوان IP الخاص بك بعد بضع مئات من الطلبات.
تصدير بيانات Pinterest التي استخرجتها
التصدير إلى CSV أو JSON
غطينا الأساسيات سابقًا. أما مع مجموعات البيانات الكبيرة جدًا (أكثر من 10,000 Pin)، ففكر في استخدام صيغة JSON Lines — كائن JSON واحد في كل سطر — لأنها أسهل في البث والمعالجة:
def save_jsonl(data, filepath="output/pins.jsonl"):
with open(filepath, "w", encoding="utf-8") as f:
for item in data:
f.write(json.dumps(item, ensure_ascii=False) + "\n")
التصدير إلى Google Sheets أو Airtable أو Notion
إذا بغيت تدفع البيانات مباشرة من Python إلى Google Sheets، فستحتاج إلى مكتبة gspread وحساب خدمة في Google Cloud. أما Airtable فيستخدم pyairtable. وبالنسبة إلى Notion فستستخدم notion-client. كل خيار يحتاج إعداد مفتاح API ويضيف تعقيدًا حقيقيًا إلى مسارك.
أو — وبصراحة، هذا أسرع طريق فعلًا — تقدر تستخدم Thunderbit لاستخراج بيانات Pinterest والتصدير إلى أي من هذه الوجهات بنقرة واحدة. لا مفاتيح API، ولا حسابات خدمة، ولا كود إضافي. يتولى Thunderbit Chrome Extension التصدير بشكل أصلي.
نصائح لتجنب الحظر أثناء استخراج بيانات Pinterest
يُصنف نظام مكافحة البوتات في Pinterest على أنه 6/10 من حيث صعوبة التجاوز بحسب ScrapeOps — مو سهل، لكنه مو الأصعب بعد. فهو يستخدم بصمة المتصفح، وتحليل السلوك، وتحديد المعدل عبر IP. هذا اللي ينفع:
- تدوير user agents: استخدم مجموعة من سلاسل Chrome الحقيقية واختر واحدة عشوائيًا لكل جلسة.
- إضافة تأخيرات عشوائية: 2–5 ثوانٍ بين التمريرات والطلبات، مع تذبذب بسيط. وإذا ما تستخدم proxies، زِدها إلى 10–15 ثانية.
- استخدام أبعاد شاشة واقعية: خلك على
viewport={"width": 1920, "height": 1080}— لا تستخدم مقاسات صغيرة أو غريبة. - فكر في proxies عند التوسع: إذا كنت تسحب آلاف الـ Pins، استخدم proxies سكنية دوارة. بدونها، توقع حظر IP بعد بضع مئات من الطلبات.
- احترم
robots.txt: ملفrobots.txtفي Pinterest يمنع معظم برامج الزحف الآلية ويحتوي على نحو 180 قاعدة منع. انتبه لهذا من ناحية الامتثال. - تجنب الاستخراج بعد تسجيل الدخول: التزم بالمحتوى العام المرئي وأنت غير مسجل الدخول. الاستخراج خلف تسجيل الدخول يرفع المخاطر القانونية والتقنية.
Thunderbit يتولى تحديات مكافحة البوت وCAPTCHA تلقائيًا عبر محركه الذكي — وهذا شيء أقل عليك صيانته إذا اخترت المسار بدون كود.
الاعتبارات القانونية والأخلاقية لاستخراج بيانات Pinterest
بختصر هنا لأن هذا مو محور المقال، لكنه مهم.
تنص شروط خدمة Pinterest (القسم 2a) على أنك توافق على عدم "scrape, collect, search, copy or otherwise access data or content from Pinterest in unauthorized ways, such as by using automated means (without our express prior permission)." ومع ذلك، تميل المحاكم عمومًا إلى اعتبار استخراج البيانات المتاحة علنًا غير مخالف لقانون Computer Fraud and Abuse Act — راجع hiQ v. LinkedIn وقضية Meta v. Bright Data (يناير 2024)، حيث حكمت المحكمة بأن استخراج البيانات المرئية للعامة أثناء عدم تسجيل الدخول قانوني.
بعض القواعد الأساسية:
- استخرج فقط المحتوى العام المرئي وأنت غير مسجل الدخول
- لا تستخدم البيانات المستخرجة في الرسائل المزعجة أو لانتحال شخصية المستخدمين
- احترم حقوق الصور — استخرج البيانات الوصفية متى أمكن، وتجنب إعادة توزيع الصور المحمية بحقوق النشر تجاريًا من دون إذن
- إذا كنت تنوي استخدام البيانات المستخرجة لأغراض تجارية، فاستشر محاميًا
ولفهم المشهد القانوني بشكل أعمق، راجع دليلنا حول الآثار القانونية لاستخراج البيانات من الويب.
الخلاصة: ما الذي تعلمته وإلى أين تتجه بعد ذلك
أنت الآن تعرف لماذا يفشل الاستخراج الثابت على Pinterest (لأنه تطبيق React SPA — لا JavaScript، لا بيانات)، وكيف تستخدم Playwright لاستخراج نتائج البحث واللوحات وملفات المستخدمين، وكيف تبني معالج تمرير لانهائي احترافي ما يتوقف عند 16 Pin، وكيف تحصل على صور كاملة الدقة بدل الصور المصغرة الصغيرة.
ملخص سريع لأهم النقاط:
requests+ BeautifulSoup ما راح يشتغلان مع Pinterest. لا تضيع وقتك.- Playwright هو أفضل أداة Python لهذي المهمة — سريع، مدعوم جيدًا، ويتعامل مع عرض JavaScript بشكل أصلي.
- التمرير اللانهائي يحتاج حلقة تمرير مبنية على إزالة التكرار، وليس عددًا ثابتًا من التمريرات.
- الصور عالية الدقة تحتاج إعادة كتابة مسار الرابط — استهدف
/736x/(لأن/originals/غالبًا يرجع 403). - استخراج اللوحات والملفات الشخصية مو مغطى كثير في الشروحات الحالية، لكنه سهل نسبيًا إذا استخدمت المحددات الصحيحة.
- لغير المبرمجين أو للفرق اللي تبغى السرعة، يتيح لك Thunderbit استخراج بيانات Pinterest في خطوتين وتصديرها إلى Google Sheets أو Excel أو Airtable أو Notion — بدون الحاجة إلى Python. جرّبه مجانًا عبر Chrome Extension.
إذا كنت تبني pipeline بـ Python، فالكود الموجود في هذا الدليل يعطيك أساسًا قويًا. وإذا كنت تحتاج فقط إلى البيانات، فThunderbit هو الاختصار. في الحالتين، ما عاد أنت عالق مع 16 Pin ونظرة حيرة.
ولمزيد من المعلومات حول الاستخراج وجمع البيانات، اطلع على أدلتنا حول كيفية استخراج البيانات من الويب باستخدام Python، وأفضل أدوات استخراج الويب الآلية، واستخراج البيانات من موقع إلى Excel. وتقدر أيضًا تستكشف أسعار Thunderbit أو تشاهد الشروحات على قناة Thunderbit على YouTube.
الأسئلة الشائعة
1. هل يمكن استخراج بيانات Pinterest باستخدام BeautifulSoup؟
ليس بكفاءة إذا استخدمته وحده. Pinterest يعرض كل المحتوى عبر JavaScript، لذلك فإن requests + BeautifulSoup ترى فقط هيكل HTML فاضي. تحتاج إلى متصفح headless مثل Playwright أو Selenium لعرض الصفحة أولًا، أو تقدر تستخدم أداة بدون كود مثل Thunderbit تتولى عرض JavaScript تلقائيًا.
2. كم عدد الـ Pins اللي أقدر أستخرجها من Pinterest في جلسة واحدة؟
يعتمد هذا على منطق التمرير وطريقة التعامل مع مكافحة البوت. باستخدام معالج التمرير اللانهائي الجاهز للإنتاج في هذا الدليل (إزالة التكرار، والمهلة، ومنطق إعادة المحاولة)، تقدر تستخرج مئات إلى آلاف الـ Pins لكل لوحة أو استعلام بحث بشكل موثوق. أما اللوحات الكبيرة جدًا، فتوقع تقضي عدة دقائق في التمرير والجمع.
3. ليه صور Pinterest اللي استخرجتها تطلع صغيرة جدًا؟
افتراضيًا، Pinterest يقدّم صورًا مصغرة /236x/ في عرض الشبكة. للحصول على دقة أعلى، أعد كتابة مسار الرابط إلى /736x/ أو /originals/. لاحظ أن /originals/ صار يرسل أخطاء 403 بشكل متزايد حتى 2025، لذلك /736x/ هو الحد الأعلى الموثوق.
4. هل استخراج بيانات Pinterest قانوني؟
استخراج البيانات العامة المتاحة علنًا مقبول عمومًا وفق أحكام قضائية حديثة (مثل hiQ v. LinkedIn وMeta v. Bright Data)، لكن شروط خدمة Pinterest تمنع الوصول الآلي غير المصرح به. التزم بالمحتوى العام، ولا تستخدم البيانات في الرسائل المزعجة، واحترم حقوق النشر، واستشر مستشارًا قانونيًا في الاستخدامات التجارية.
5. ما هو أفضل بديل بدون كود لاستخراج بيانات Pinterest؟
يمكن لـ Thunderbit AI Web Scraper استخراج بيانات Pins في Pinterest — مثل العناوين والصور والروابط والوصف — في خطوتين فقط، مع تصدير مدمج إلى Google Sheets أو Excel أو Airtable أو Notion. كما أنه يتعامل تلقائيًا مع عرض JavaScript والتمرير اللانهائي وتحديات مكافحة البوت، لذلك ما تحتاج تكتب أو تصين أي كود.
اعرف المزيد


