גרידת Pinterest עם Python: "Pins, Boards וגלילה אינסופית"

עודכן לאחרונה ב- April 17, 2026
גרידת Pinterest עם Python: "Pins, Boards וגלילה אינסופית"

לפני כמה חודשים אחד המהנדסים שלנו הראה לי סקריפט Python שכתב בסוף השבוע. המטרה שלו הייתה לשלוף תמונות השראה למוצרים מ-Pinterest עבור פרויקט מחקר שוק. הוא הריץ את הסקריפט, והתוצאה הייתה… 16 Pins. מתוך Board של יותר מ-2,000. הוא בהה במסך, אחר כך בי, ואמר: "אני חושב ש-Pinterest עושה ממני צחוק."

הוא ממש לא היחיד. זו בלי ספק התסכול הכי נפוץ שאני רואה אצל מפתחים שמנסים לגרד נתונים מ-Pinterest עם Python. מפעילים requests ו-BeautifulSoup, נכנסים לכתובת של Pinterest, ומקבלים או קומץ פריטים או מעטפת HTML ריקה. למה זה קורה? כי Pinterest היא אפליקציית SPA שמרונדרת כולה ב-JavaScript — בקשת HTTP סטטית פשוט לא רואה את התוכן האמיתי. במדריך הזה אסביר למה זה קורה, אילו שיטות באמת עובדות (Playwright, יירוט API פנימי, וגם כלים ללא קוד כמו Thunderbit), ואביא דוגמאות קוד שלב-אחר-שלב לגרידה של Pins, Boards, פרופילי משתמשים, Infinite Scroll ותמונות ברזולוציה מלאה. אם אתם רוצים לבנות סקרייפר ברמת production או פשוט למשוך נתונים במהירות — המאמר הזה בשבילכם.

מהי גרידת Pinterest?

גרידת Pinterest היא תהליך של חילוץ נתונים מפלטפורמת Pinterest בצורה אוטומטית — למשל תמונות של Pins, כותרות, תיאורים, שמות Boards, מספרי עוקבים וכתובות URL. במקום לגלוש ידנית ולשמור Pins אחד-אחד, משתמשים בקוד (או בכלי) כדי לאסוף נתונים מובנים מתוצאות חיפוש, Boards או פרופילים בקנה מידה גדול.

עם מעל 240 מיליארד Pins בפלטפורמה ו-619 מיליון משתמשים פעילים חודשית נכון לסוף 2025, Pinterest היא אחד ממקורות הנתונים הוויזואליים העשירים ביותר ברשת. עבור עסקים, זה זהב — בין אם אתם עוקבים אחרי טרנדים במוצרים, בודקים תוכן של מתחרים או בונים רשימות לפנייה למשפיענים.

למה לגרד Pinterest עם Python?

Pinterest כבר מזמן לא רק לוח השראה למתכנני חתונות. זהו כלי רציני ל-Business Intelligence — 85% ממשתמשי Pinterest השבועיים רכשו משהו בעקבות Pin של מותג, ו-96–97% מהחיפושים המובילים הם ללא מותג, כלומר המשתמשים מגיעים עם כוונה, אבל בלי נאמנות למותג מסוים. זו הזדמנות עצומה לגילוי — והיא מסבירה למה כל כך הרבה צוותים רוצים נתוני Pinterest מסודרים.

כך זה נראה לפי צוותים:

צוותנתונים נדרשיםערך עסקי
תפעול Ecommerceתמונות מוצרים, מחירים, אסתטיקה טרנדיתתמחור תחרותי, מלאי שמבוסס על טרנדים
שיווקביצועי Boards, מעורבות ב-Pins, תוכן של מתחריםאסטרטגיית תוכן, השוואת קמפיינים
מכירות / יצירת לידיםפרופילים של יוצרים, מספרי עוקבים, פרטי קשרפנייה למשפיענים, מיקוד בשיתופי פעולה
נדל"ןPins של עיצוב בית, טרנדים בעיצוב, פריסות חדריםצילום נכסים, הנחיות לסטייג'ינג
יוצרי תוכןנושאים חמים, פורמטים פופולריים, נושאים עונתייםלוח תוכן, מחקר על סגנון ויזואלי

והנה הקאץ': ה-API הרשמי של Pinterest מוגבל. הוא דורש חשבון עסקי, אישור (כולל הדגמת וידאו של האפליקציה), ומספק גישה רק לנתונים של החשבון שלכם. אם רוצים לעיין ב-Boards ציבוריים, בתוצאות חיפוש או בפרופילים של מתחרים — גרידה היא האלטרנטיבה הפרקטית. לכן הרבה צוותים פונים ל-Python — או לכלים ללא קוד כמו Thunderbit כשצריך תוצאות בלי כל הסיבוך.

למה BeautifulSoup לבד נכשל ב-Pinterest ומה כן עובד באמת

אם ניסיתם לגרד את Pinterest עם requests + BeautifulSoup וקיבלתם 16 פריטים או דף ריק, אתם לא מדמיינים. Pinterest בנויה עם React וכל התוכן שלה מרונדר ב-100% באמצעות JavaScript. כשמבקשים URL של Pinterest עם בקשת HTTP רגילה, השרת מחזיר שלד HTML מינימלי — כמה תגיות <link> ו-<script>, ו-<div> ריק שבו React “מעלה” את האפליקציה. כל כרטיסי ה-Pin, התמונות, הכותרות והגריד מוזרקים רק אחרי ש-JavaScript רץ בדפדפן.

אין הרצת JavaScript = אין Pins.

אז מה כן עובד? הנה השוואה בין השיטות העיקריות:

גישהתומכת ב-JS?משיגה את כל הנתונים?מורכבותמתאימה במיוחד ל...
requests + BeautifulSoupלא~0–16 פריטיםנמוכהלא מתאימה ל-Pinterest
Selenium / Playwrightכןכן, עם לוגיקת גלילהבינוניתשליטה מלאה, תהליכי Python
יירוט API פנימי של Pinterestכןכן, JSON מחולק לעמודיםגבוההמקסימום נתונים, בלי דפדפן
Scraper API של צד שלישיכןמשתנהנמוכהסקייל בלי תשתית
כלי ללא קוד (Thunderbit)כןמובנה באמצעות AIנמוכה מאודמשתמשים לא טכניים, תוצאות מהירות

למדריך הזה אני ממליץ על Playwright כפתרון Python. הוא מרנדר JavaScript, תומך בסימולציית גלילה, מתוחזק היטב (78,600+ כוכבים ב-GitHub, עם צמיחה של 180% משנה לשנה במודעות דרושים), והוא מהיר ב-35–45% מ-Selenium במדדים שונים. אם אתם מעדיפים דרך ללא קוד — גם לזה נגיע.

ה-API הרשמי של Pinterest מול גרידה ב-Python מול No-Code: מה עדיף?

לפני שמתחילים לכתוב קוד, כדאי לשאול: בכלל צריך? הנה מסגרת החלטה:

קריטריוןPinterest APIגרידה ב-PythonThunderbit (ללא קוד)
נדרש אישורחשבון עסקי + הדגמת וידאולאלא
גישה ל-Pins/Boards ציבורייםמוגבלת (רק נתוני החשבון)מלאהמלאה
הורדת תמונות ברזולוציה מלאהמשתנהכן, באמצעות ניתוח URLכן, באמצעות חילוץ תמונות
טיפול ב-Infinite Scrollלא רלוונטיכן, עם קודאוטומטי
תחזוקה נדרשתנמוכהגבוהה (סלקטורים נשברים)אין (AI מסתגל)
ייצוא ל-Sheets/Airtableידניקוד מותאם אישיתמובנה
זמן הקמהשעות–ימים30–60 דק׳2 דקות

אם אתם משווקים, אנשי תפעול ב-ecommerce, או פשוט רוצים נתוני Pinterest בגיליון בלי לכתוב או לתחזק סקריפטי Python, Thunderbit AI Web Scraper הוא המסלול המהיר. פותחים כל דף Pinterest, לוחצים "AI Suggest Fields", אחר כך "Scrape", ומייצאים ישר ל-Google Sheets, Excel, Airtable או Notion. תכונת הגרידה של תתי-עמודים יכולה אפילו לעקוב אחרי קישורי Pin בודדים ולהעשיר את הנתונים אוטומטית. ראיתי חברי צוות שמעולם לא כתבו שורת קוד אחת מושכים יותר מ-500 Pins ל-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

נרכיב את URL החיפוש על ידי הכנסת שאילתת החיפוש לתבנית:

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)  # מחכים לטעינת ה-JS וה-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 — זה מונע תווים משובשים.

גרידת Boards שלמים ופרופילי משתמשים ב-Pinterest

זו חסרה גדולה במדריכים הקיימים. לא מצאתי מדריך מתחרה אחד שמכסה לעומק גרידת Boards או פרופילים — למרות שזו אחת הדרישות הכי נפוצות בפורומים. משתמשים רוצים להוריד את כל ה-Pins מ-Board מסוים, לארגן תמונות לתיקיות לפי Board, ולשלוף נתוני פרופיל כמו מספר עוקבים ורשימת Boards.

גרידת כל ה-Pins מכתובת של Board

כתובות Board נראות כך: https://www.pinterest.com/{username}/{board-name}/. מבנה ה-DOM דומה לתוצאות חיפוש — ה-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 {scroll_round + 1}: {len(all_pins)} pins ייחודיים נאספו")
            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

דבר אחד שצריך לשים לב אליו: בעמודי Board יש לפעמים לשונית "More Ideas" שמפרידה בין Pins ששמרתם לבין המלצות אלגוריתמיות. אם רוצים רק את ה-Pins השמורים של המשתמש, כדאי לעצור בגלילה כשהמפריד הזה מופיע.

גרידת פרופיל משתמש: Boards, מספר עוקבים ו-Pins

כתובות פרופיל נראות כך: https://www.pinterest.com/{username}/. מדף פרופיל אפשר לשלוף:

  • מספר עוקבים/נעקבים: חפשו div[data-test-id='follower-count']
  • רשימת Boards: כל Board הוא כרטיס עם קישור ל-/{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 "N/A"

        # חילוץ קישורים ל-Boards
        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 בכל ה-Boards של פרופיל, עוברים על רשימת ה-Boards ומפעילים scrape_board() עבור כל אחד. אפשר גם לארגן את התמונות שהורדו אוטומטית לתיקיות נפרדות לפי Board.

בניית handler מקצועי ל-Infinite Scroll

זה החלק שמבדיל בין סקרייפר צעצוע לסקרייפר אמיתי. נקודת הכאב מספר 1 — וראיתי אותה בלפחות תריסר שרשורי פורום — היא שסקרייפרים מחזירים רק 16–25 פריטים כי הם לא גוללים מספיק, או שהם משתמשים במספר גלילות קבוע כמו for i in range(5): scroll() ומקווים לטוב.

זה לא אמין. Pinterest טוענת תוכן חדש במנות של כ-25 Pins, שמופעלות על-ידי אירועי גלילה. אם תגללו חמש פעמים, אולי תקבלו 125 Pins — או 75 אם הרשת איטית, או 150 אם המנות קטנות. צריך דפוס חכם יותר.

דפוס גלול-עד-שאין-תוכן-חדש

הנה פונקציית גלילה יציבה שעוקבת אחרי מזהים ייחודיים של Pins, משתמשת ב-timeout שניתן להגדיר, כוללת לוגיקת retry ומדפיסה התקדמות:

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 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 {i+1}: {new_this_round} Pins חדשים | {len(all_pins)} Pins ייחודיים בסך הכול")

        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("  לא נמצאו Pins חדשים ב-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

למה זה עובד טוב:

  • Deduplication לפי href: לכל Pin יש URL ייחודי, ולכן משתמשים בו כמזהה. זה מונע ספירה כפולה כשה-DOM נבנה מחדש בזמן הגלילה.
  • כלל שלוש הפעמים: אם שלוש גלילות רצופות לא מחזירות שום Pin חדש, עוצרים. זה מטפל במצב שבו הדף עדיין נטען אבל אין עוד תוכן.
  • ג׳יטר אקראי בהשהיה: הוספת 0.5–1.5 שניות אקראיות בין גלילות גורמת לפעולה להיראות אנושית יותר ומפחיתה את הסיכוי להפעיל מנגנוני anti-bot.
  • מגבלת max_scrolls: מונעת לולאות אינסופיות אם משהו משתבש.

טיפול במקרי קצה

  • שבירת "More Ideas": בדפי Board, Pinterest לפעמים מוסיפה מקטע "More Ideas". אם אתם רוצים רק את ה-Pins המקוריים של ה-Board, אפשר לזהות את האלמנט הזה ולעצור בגלילה כשהוא מופיע.
  • Rate limiting בסשנים ארוכים: אם אתם גוללים ב-Board עם אלפי Pins, Pinterest עלולה להתחיל להגביל תגובות. אם אתם רואים גלילות שמייצרות אפס Pins חדשים מדי פעם (אבל לא שלוש ברצף), הגדילו את ההשהיה ל-5 שניות ומעלה.

קבלת תמונות Pinterest ברזולוציה מלאה (לא thumbnails)

זה משגע אנשים. מגרדים הרבה Pins, מורידים את התמונות, והן כולן thumbnails זעירים של 236 פיקסלים. משתמשים בפורומים מתארים את זה כ"איכות זבל, כמו גודל קטן מדי". הפתרון הוא להבין את מבנה כתובות התמונות של Pinterest.

מבנה נתיב ה-URL של תמונות Pinterest

כל תמונות Pinterest מוגשות מ-https://i.pinimg.com/{size}/{hash}.jpg. החלק {size} קובע את הרזולוציה:

נתיב גודלממדיםשימוש
/236x/רוחב 236pxתצוגת גריד ברירת מחדל (מה שמקבלים בדרך כלל)
/474x/רוחב 474pxרזולוציה בינונית
/736x/רוחב 736pxתצוגת Pin מורחבת
/originals/מידות ההעלאה המקוריותרזולוציה מלאה

פונקציית עזר: שדרוג כל URL של תמונת Pinterest לרזולוציה מלאה

הנה פונקציה שמשכתבת כל URL של תמונת Pinterest לאיכות הגבוהה ביותר הזמינה, עם לוגיקת fallback:

import requests as req

def upgrade_image_url(url, preferred_size="originals"):
    """משכתבת URL של תמונת 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))

כדאי להוסיף השהיית rate limiting בין הורדות. אני משתמש ב-1.5–2.3 שניות עם ג׳יטר. בלי זה, Pinterest תחסום את ה-IP שלכם אחרי כמה מאות בקשות.

ייצוא נתוני Pinterest שגרדתם

ייצוא ל-CSV או JSON

כבר עברנו על הבסיס. עבור דאטה-סטים גדולים (10,000+ Pins), שווה לשקול 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 service account. עבור Airtable, משתמשים ב-pyairtable. עבור Notion, ב-notion-client. כל אחד מהם דורש הגדרת API key ומוסיף מורכבות אמיתית ל-pipeline.

או — ואני קצת משוחד כאן, אבל זו באמת הדרך המהירה ביותר — אפשר להשתמש ב-Thunderbit כדי לגרד את Pinterest ולייצא לכל היעדים האלה בלחיצה אחת. בלי API keys, בלי service accounts, בלי קוד נוסף. הרחבת Chrome של Thunderbit מטפלת בייצוא באופן מובנה.

טיפים להימנע מחסימה בזמן גרידת Pinterest

מערכת האנטי-בוט של Pinterest מקבלת ציון קושי עקיפה 6/10 לפי ScrapeOps — לא טריוויאלית, אבל גם לא היעד הקשה ביותר. היא משתמשת בטביעת אצבע של הדפדפן, ניתוח התנהגות והגבלת קצב לפי IP. הנה מה שעובד:

  • סיבוב User-Agents: השתמשו במאגר של מחרוזות Chrome אמיתיות ובחרו אחת אקראית לכל סשן.
  • הוספת השהיות אקראיות: 2–5 שניות בין גלילות ובקשות, עם ג׳יטר. בלי פרוקסי, עדיף להגדיל ל-10–15 שניות.
  • Viewport ריאלי: הגדירו viewport={"width": 1920, "height": 1080} — לא מידות קטנות או חריגות.
  • פרוקסי לסקייל: אם אתם מגרדים אלפי Pins, סובבו residential proxies. בלי זה, צפויים חסימות IP אחרי כמה מאות בקשות.
  • כבדו את robots.txt: ה-robots.txt של Pinterest חוסם רוב הסורקים האוטומטיים ויש בו כ-180 כללי disallow. קחו זאת בחשבון מבחינת תאימות.
  • הימנעו מגרידה בזמן התחברות: הישארו עם תוכן ציבורי בלבד, כשהחשבון לא מחובר. גרידה מאחורי התחברות מעלה גם סיכון משפטי וגם סיכון טכני.

Thunderbit מטפל אוטומטית באנטי-בוט ובאתגרי CAPTCHA דרך מנוע ה-AI שלו — עוד דבר אחד פחות לתחזק אם בוחרים במסלול ללא קוד.

שיקולים משפטיים ואתיים בגרידת Pinterest

אשמור את זה קצר כי זה לא מוקד המאמר, אבל זה חשוב.

תנאי השימוש של Pinterest (סעיף 2a) קובעים שאתם מסכימים לא "לגרד, לאסוף, לחפש, להעתיק או לגשת אחרת לנתונים או תוכן מ-Pinterest בדרכים לא מורשות, למשל באמצעות אמצעים אוטומטיים (ללא אישור מפורש מראש שלנו)." עם זאת, בתי משפט קבעו בדרך כלל שגרידת נתונים ציבוריים אינה מפרה את חוק Computer Fraud and Abuse Act — ראו hiQ נגד LinkedIn ו-Meta נגד Bright Data (ינואר 2024), שם קבע בית המשפט שגרידה של נתונים גלויים לציבור כאשר לא מחוברים לחשבון היא חוקית.

כמה כללי אצבע:

  • גרדו רק תוכן ציבורי כאשר אינכם מחוברים לחשבון
  • אל תשתמשו בנתונים שגרדתם לספאם או להתחזות למשתמשים
  • כבדו זכויות יוצרים על תמונות — שלפו מטא-דאטה כשאפשר, והימנעו מהפצה מסחרית של תמונות מוגנות בלי אישור
  • אם אתם מתכננים להשתמש בנתונים שגרדתם למטרה מסחרית, דברו עם עורך דין

למבט עמוק יותר על ההיבט המשפטי, ראו את המדריך שלנו על השלכות משפטיות של גרידת נתונים מהאינטרנט.

סיכום: מה למדתם ולאן ממשיכים מכאן

עכשיו אתם יודעים למה גרידה סטטית נכשלת ב-Pinterest (זו SPA מבוססת React — בלי JavaScript אין נתונים), איך להשתמש ב-Playwright כדי לגרד תוצאות חיפוש, Boards ופרופילי משתמשים, איך לבנות handler אמין ל-Infinite Scroll שלא נעצר אחרי 16 Pins, ואיך להגיע לתמונות ברזולוציה מלאה במקום thumbnails זעירים.

תקציר קצר של מה שחשוב:

  • requests + BeautifulSoup לא יעבדו על Pinterest. אל תבזבזו על זה זמן.
  • Playwright הוא כלי Python הטוב ביותר למשימה — מהיר, נתמך היטב, ומרנדר JavaScript באופן טבעי.
  • Infinite Scroll דורש לולאת גלילה מבוססת deduplication, לא מספר קבוע של גלילות.
  • תמונות ברזולוציה מלאה דורשות שכתוב של נתיב ה-URL — עדיף /736x/ (כי /originals/ מחזיר לעיתים קרובות 403).
  • גרידת Boards ופרופילים כמעט לא מקבלת מענה במדריכים קיימים, אבל היא פשוטה יחסית עם הסלקטורים הנכונים.
  • למי שלא כותב קוד או לצוותים שרוצים מהירות, Thunderbit מאפשר לגרד Pinterest בשתי לחיצות ולייצא ל-Google Sheets, Excel, Airtable או Notion — בלי צורך ב-Python. אפשר לנסות בחינם דרך הרחבת Chrome.

אם אתם בונים pipeline ב-Python, הקוד במדריך הזה נותן בסיס חזק. אם אתם פשוט צריכים את הנתונים, Thunderbit הוא קיצור הדרך. בכל מקרה, כבר לא תישארו תקועים עם 16 Pins ומבט מבולבל.

לקריאה נוספת על גרידה וחילוץ נתונים, בדקו את המדריכים שלנו על איך לגרד נתונים מהאינטרנט עם Python, הכלים האוטומטיים הטובים ביותר לגרידת נתונים מהאינטרנט, ו-גרידת נתונים מאתר ל-Excel. אפשר גם לבדוק את תמחור Thunderbit או לצפות במדריכים ב-ערוץ YouTube של Thunderbit.

שאלות נפוצות

1. האם אפשר לגרד Pinterest עם BeautifulSoup?

לא בצורה יעילה לבדו. Pinterest מרנדרת את כל התוכן ב-JavaScript, לכן requests + BeautifulSoup רואה רק מעטפת HTML ריקה. צריך דפדפן headless כמו Playwright או Selenium כדי לרנדר את הדף קודם, או להשתמש בכלי ללא קוד כמו Thunderbit שמטפל ב-JS אוטומטית.

2. כמה Pins אפשר לגרד מ-Pinterest בסשן אחד?

זה תלוי בלוגיקת הגלילה ובהתמודדות עם אנטי-בוט. עם handler ל-Infinite Scroll ברמת production כמו במדריך הזה (deduplication, timeout, retry logic), אפשר לגרד באופן אמין מאות עד אלפי Pins לכל Board או שאילתת חיפוש. עבור Boards גדולים מאוד, צפו לכמה דקות של גלילה ואיסוף.

3. למה התמונות שגרדתי מ-Pinterest יוצאות קטנות?

ברירת המחדל של Pinterest היא thumbnails ב-/236x/ בתצוגת הגריד. כדי לקבל רזולוציה גבוהה יותר, משכתבים את נתיב התמונה ל-/736x/ או ל-/originals/. שימו לב ש-/originals/ מחזיר יותר ויותר שגיאות 403 נכון ל-2025, ולכן /736x/ הוא המקסימום האמין.

4. האם חוקי לגרד Pinterest?

גרידת נתונים ציבוריים מקובלת בדרך כלל לפי פסיקות עדכניות (למשל hiQ נגד LinkedIn, Meta נגד Bright Data), אבל תנאי השימוש של Pinterest אוסרים גישה אוטומטית לא מורשית. הישארו עם תוכן ציבורי, אל תשתמשו בנתונים לספאם, כבדו זכויות יוצרים, והתייעצו עם ייעוץ משפטי לשימוש מסחרי.

5. מה החלופה הטובה ביותר ללא קוד לגרידת Pinterest?

Thunderbit AI Web Scraper יכול לחלץ נתוני Pins מ-Pinterest — כותרות, תמונות, כתובות URL, תיאורים — בשתי לחיצות, עם ייצוא מובנה ל-Google Sheets, Excel, Airtable או Notion. הוא מטפל ברינדור JavaScript, ב-Infinite Scroll ובאתגרי אנטי-בוט אוטומטית, כך שלא צריך לכתוב או לתחזק קוד.

למידע נוסף

Shuai Guan
Shuai Guan
מנכ"ל Thunderbit | מומחה לאוטומציה של נתונים באמצעות AI Shuai Guan הוא המנכ"ל של Thunderbit ובוגר הפקולטה להנדסה של אוניברסיטת מישיגן. עם כמעט עשור של ניסיון בטכנולוגיה ובארכיטקטורת SaaS, הוא מתמחה בהפיכת מודלים מורכבים של AI לכלי חילוץ נתונים פרקטיים, ללא קוד. בבלוג הזה הוא משתף תובנות ישירות מהשטח, שנבחנו בפועל, על Web Scraping ואסטרטגיות אוטומציה שיעזרו לכם לבנות תהליכי עבודה חכמים יותר, מבוססי נתונים. כשאינו משפר תהליכי נתונים, הוא מביא את אותה תשומת לב לפרטים גם לתשוקה שלו לצילום.
תוכן עניינים

גרדו דף אינטרנט פשוט על ידי בקשה

תגידו מה צריך באנגלית פשוטה. או אפילו לא צריך להגיד כלום.

נסו את Thunderbit חינם
חילוץ נתונים באמצעות AI
העבירו נתונים בקלות ל-Google Sheets, Airtable או Notion
Chrome Store Rating
PRODUCT HUNT#1 Product of the Week