Kilka miesięcy temu jeden z naszych inżynierów pokazał mi skrypt w Pythonie, który napisał w weekend. Miał pobierać obrazy inspiracji produktowych z Pinteresta na potrzeby projektu badania rynku. Uruchomił go i wynik był… 16 pinów. Z tablicy liczącej ponad 2 000. Wpatrywał się w ekran, potem na mnie, po czym powiedział: „Chyba Pinterest się ze mnie nabija”.
Nie był sam. To bez dwóch zdań najczęstsza frustracja, jaką widzę u programistów próbujących scrapować Pinteresta w Pythonie. Odpalasz requests i BeautifulSoup, wchodzisz na adres Pinteresta i dostajesz garść elementów albo pusty szkielet HTML. Dlaczego? Bo Pinterest to aplikacja typu single-page, renderowana w całości po stronie JavaScript — zwykłe żądanie HTTP nie zobaczy właściwej zawartości. W tym poradniku pokażę Ci, dlaczego tak się dzieje, jakie metody naprawdę działają (Playwright, przechwytywanie wewnętrznego API oraz narzędzia no-code, takie jak Thunderbit), a także dam Ci kod krok po kroku do pobierania pinów, tablic, profili użytkowników, nieskończonego przewijania i obrazów w pełnej rozdzielczości. Niezależnie od tego, czy chcesz zbudować scraper gotowy do użycia w produkcji, czy po prostu szybko pobrać dane, ten artykuł pomoże Ci to zrobić.
Czym jest scraping Pinteresta?
Scraping Pinteresta to programowe wyciąganie danych z tej platformy — takich jak obrazy pinów, tytuły, opisy, nazwy tablic, liczba obserwujących czy adresy URL. Zamiast ręcznie przeglądać i zapisywać piny jeden po drugim, używasz kodu (lub narzędzia), aby masowo zbierać uporządkowane dane z wyników wyszukiwania, tablic albo profili użytkowników.
Przy ponad 240 miliardach Pinów na platformie i 619 milionach aktywnych użytkowników miesięcznie pod koniec 2025 roku Pinterest jest jednym z najbogatszych źródeł danych wizualnych w sieci. Dla firm te dane są na wagę złota — niezależnie od tego, czy śledzisz trendy produktowe, porównujesz treści konkurencji, czy budujesz listy do outreachu influencerów.
Dlaczego warto scrapować Pinteresta w Pythonie?
Pinterest to już nie tylko tablica inspiracji dla organizatorek wesel. To poważna platforma do analizy biznesowej — 85% osób korzystających z Pinteresta co tydzień kupiło coś na podstawie pinów marki, a 96–97% najpopularniejszych wyszukiwań nie zawiera nazwy marki, co oznacza, że użytkownicy przychodzą z intencją zakupu, ale bez lojalności wobec marki. To ogromna szansa na odkrywanie nowych tematów — i właśnie dlatego tyle zespołów chce mieć dostęp do uporządkowanych danych z Pinteresta.
Tak to wygląda w praktyce dla różnych działów:
| Zespół | Potrzebne dane | Wartość biznesowa |
|---|---|---|
| Operacje e-commerce | Zdjęcia produktów, ceny, modne estetyki | Konkurencyjne ceny, stany magazynowe oparte na trendach |
| Marketing | Wyniki tablic, zaangażowanie pinów, treści konkurencji | Strategia contentowa, benchmarki kampanii |
| Sprzedaż / lead gen | Profile twórców, liczba obserwujących, dane kontaktowe | Outreach do influencerów, targetowanie partnerstw |
| Nieruchomości | Piny z home stagingiem, trendy w wystroju, układy pomieszczeń | Zdjęcia ofert, wskazówki dotyczące aranżacji |
| Twórcy treści | Trendujące tematy, popularne formaty, sezonowe motywy | Kalendarz treści, analiza stylu wizualnego |
A teraz sedno: oficjalne API Pinteresta jest mocno ograniczone. Wymaga konta firmowego, akceptacji (w tym wideoprezentacji aplikacji) i daje dostęp wyłącznie do danych własnego konta. Jeśli chcesz przeglądać publiczne tablice, wyniki wyszukiwania albo profile konkurencji, scraping jest praktyczną alternatywą. Dlatego tak wiele zespołów sięga po Pythona — albo po narzędzia no-code, takie jak Thunderbit, gdy zależy im na wynikach bez konfiguracji.
Dlaczego samo BeautifulSoup zawodzi na Pintereście i co naprawdę działa
Jeśli próbowałeś scrapować Pinteresta przez requests + BeautifulSoup i dostałeś 16 elementów albo pustą stronę, to nie wymyślasz sobie tego. Pinterest jest zbudowany w React i renderuje 100% treści przez JavaScript. Gdy pobierasz URL Pinteresta zwykłym żądaniem HTTP, serwer zwraca minimalny szkielet HTML — kilka tagów <link> i <script> oraz pusty <div>, w którym React dopiero montuje aplikację. Wszystkie karty pinów, obrazy, tytuły i układy siatki są wstrzykiwane dopiero po wykonaniu JavaScriptu w przeglądarce.
Brak wykonania JavaScriptu = brak pinów.
Co więc działa? Oto porównanie głównych podejść:
| Podejście | Obsługuje JS? | Pobiera pełne dane? | Złożoność | Najlepsze do |
|---|---|---|---|---|
requests + BeautifulSoup | Nie | ~0–16 elementów | Niska | Nie nadaje się do Pinteresta |
| Selenium / Playwright | Tak | Tak, z logiką przewijania | Średnia | Pełna kontrola, pipeline’y w Pythonie |
| Przechwycenie wewnętrznego API Pinteresta | Tak | Tak, dane JSON z paginacją | Wysoka | Maksimum danych, bez przeglądarki |
| Zewnętrzne Scraper API | Tak | Zależnie od usługi | Niska | Skalowanie bez własnej infrastruktury |
| Narzędzie no-code (Thunderbit) | Tak | Strukturyzowane przez AI | Bardzo niska | Osoby nietechniczne, szybkie wyniki |
Do tego poradnika polecam Playwright jako podejście w Pythonie. Renderuje JavaScript, obsługuje symulację przewijania, jest dobrze utrzymywany (78 600+ gwiazdek na GitHubie, wzrost liczby ofert pracy o 180% r/r) i jest 35–45% szybszy od Selenium w benchmarkach. Jeśli wolisz podejście no-code, też je omówię.
Oficjalne API Pinteresta vs. scraping w Pythonie vs. no-code: co wybrać?
Zanim zaczniesz pisać kod, warto zadać sobie pytanie: czy naprawdę musisz? Oto proste ramy decyzyjne:
| Kryterium | API Pinteresta | Scraping w Pythonie | Thunderbit (no-code) |
|---|---|---|---|
| Wymagana akceptacja | Konto firmowe + demo wideo | Brak | Brak |
| Dostęp do publicznych pinów/tablic | Ograniczony (tylko własne dane) | Pełny | Pełny |
| Pobieranie obrazów w pełnej rozdzielczości | Zależnie od danych | Tak, przez analizę URL | Tak, przez ekstrakcję obrazów |
| Obsługa nieskończonego przewijania | Nie dotyczy | Tak, z kodem | Automatycznie |
| Konserwacja | Niska | Wysoka (selektory się psują) | Brak (AI się dostosowuje) |
| Eksport do Sheets/Airtable | Ręczny | Własny kod | Wbudowany |
| Czas konfiguracji | Godziny–dni | 30–60 min | 2 minuty |
Jeśli jesteś marketerem, osobą od operacji e-commerce albo po prostu chcesz mieć dane z Pinteresta w arkuszu bez pisania i utrzymywania skryptów w Pythonie, Thunderbit AI Web Scraper to najszybsza opcja. Otwierasz dowolną stronę Pinteresta, klikasz „AI Suggest Fields”, naciskasz „Scrape” i eksportujesz dane bezpośrednio do Google Sheets, Excela, Airtable albo Notion. Funkcja scrapowania podstron może nawet automatycznie przechodzić do pojedynczych pinów, aby wzbogacić dane. Widziałem, jak osoby, które nigdy nie napisały ani linijki kodu, wyciągały ponad 500 pinów do Google Sheet w mniej niż trzy minuty.
Jeśli natomiast zależy Ci na pełnej kontroli, chcesz wpiąć scraping do pipeline’u w Pythonie albo po prostu lubisz budować rzeczy samodzielnie — czytaj dalej.
Konfiguracja środowiska Python do scrapowania Pinteresta
- Poziom trudności: średni
- Czas potrzebny: ok. 30–60 minut (łącznie z kodowaniem i testami)
- Czego potrzebujesz: Python 3.9+, przeglądarka Chrome (do testów), dostęp do terminala / wiersza poleceń
Instalacja Playwright i zależności
Najpierw utwórz folder projektu i skonfiguruj środowisko wirtualne:
mkdir pinterest-scraper
cd pinterest-scraper
python -m venv venv
source venv/bin/activate # Na Windows: venv\Scripts\activate
Zainstaluj Playwright i pobierz binarkę przeglądarki Chromium:
pip install playwright
playwright install chromium
Do eksportu danych użyjesz też wbudowanych modułów Pythona: json, os i csv. Nie trzeba nic dodatkowo instalować.
Struktura folderów projektu
Od początku warto zachować porządek:
pinterest-scraper/
├── scraper.py
├── config.py
├── output/
│ ├── pins.json
│ └── pins.csv
└── images/
├── board-name-1/
└── board-name-2/
W pliku config.py ustaw swój user agent. Pinterest blokuje domyślne sygnatury headless browserów, więc użyj realistycznej wartości:
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"
Krok 1: zbuduj adres URL wyszukiwania na Pintereście
Utwórz URL wyszukiwania, wstawiając zapytanie do szablonu:
query = "mid century modern furniture"
url = f"https://www.pinterest.com/search/pins/?q={query.replace(' ', '%20')}&rs=typed"
Możesz to parametryzować dla dowolnej frazy. Parametr rs=typed mówi Pinterestowi, że zapytanie zostało wpisane ręcznie, a nie zasugerowane, co czasem wpływa na trafność wyników.
Krok 2: uruchom przeglądarkę headless i załaduj stronę
Oto podstawowa konfiguracja Playwright. Zwróć uwagę na własny user agent — bez niego Pinterest prawdopodobnie Cię zablokuje albo pokaże ekran logowania.
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) # Czekamy, aż JavaScript wyrenderuje początkowe piny
Po wykonaniu tego kodu na stronie powinien pojawić się początkowy zestaw pinów — zwykle 25–50.
Krok 3: wyciągnij dane pinów ze strony
Pinterest opakowuje każdy pin w div z atrybutem data-test-id='pinWrapper'. W środku znajdziesz link (<a>) z adresem pinu i tytułem (przez aria-label) oraz element <img> z adresem miniatury.
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
})
Na tym etapie results zawiera piny widoczne w początkowym obszarze ekranu. Żeby pobrać więcej, trzeba przewijać — i to prowadzi nas do najważniejszej części.
Krok 4: zapisz wyniki do JSON lub CSV
Po ekstrakcji zapisz dane do plików, żeby łatwo z nich korzystać:
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)
Jeśli planujesz otwierać CSV w Excelu, używaj kodowania utf-8-sig — to zapobiega „krzakom” w znakach.
Scrapowanie całych tablic Pinteresta i profili użytkowników
To duża luka w istniejących poradnikach. Nie udało mi się znaleźć ani jednego konkurencyjnego przewodnika, który dogłębnie omawia scraping tablic albo profili — a to jedne z najczęściej proszonych funkcji na forach. Użytkownicy chcą pobierać wszystkie piny z tablicy, porządkować obrazy w folderach dla każdej tablicy i wyciągać dane na poziomie profilu, takie jak liczba obserwujących czy lista tablic.
Pobieranie wszystkich pinów z adresu URL tablicy
Adresy tablic mają postać https://www.pinterest.com/{username}/{board-name}/. Struktura DOM jest podobna do wyników wyszukiwania — piny są opakowane w div[data-test-id='pinWrapper'] — ale trzeba przewijać stronę, żeby załadować wszystkie elementy.
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): # Limit bezpieczeństwa
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"Przewinięcie {scroll_round + 1}: zebrano {len(all_pins)} unikalnych pinów")
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 # Brak dalszej zawartości
await browser.close()
return all_pins
Na co uważać: strony tablic czasem mają zakładkę „More Ideas”, która oddziela zapisane piny od rekomendacji algorytmu. Jeśli chcesz tylko faktycznie zapisane piny użytkownika, przestań przewijać, gdy pojawi się ten separator.
Scrapowanie profilu użytkownika: tablice, liczba obserwujących i piny
Adresy profili mają formę https://www.pinterest.com/{username}/. Z poziomu profilu możesz wyciągnąć:
- Liczbę obserwujących i obserwowanych: szukaj
div[data-test-id='follower-count'] - Listę tablic: każda tablica to karta z linkiem do
/{username}/{board-name}/ - Łączną liczbę pinów: czasami widoczną w nagłówku profilu
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)
# Pobranie liczby obserwujących
follower_el = await page.query_selector("div[data-test-id='follower-count']")
followers = await follower_el.inner_text() if follower_el else "N/A"
# Pobranie linków do tablic
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}
Aby pobrać wszystkie piny ze wszystkich tablic profilu, przejdź po liście tablic i wywołaj scrape_board() dla każdej z nich. Możesz też automatycznie porządkować pobrane obrazy w folderach przypisanych do konkretnych tablic.
Budowa produkcyjnego handlera nieskończonego przewijania
To właśnie ten fragment odróżnia zabawkowy scraper od prawdziwego narzędzia. Główny problem — i widziałem go w co najmniej kilkunastu wątkach na forach — polega na tym, że scraper zwraca tylko 16–25 elementów, bo nie przewija wystarczająco długo albo używa stałej liczby przewinięć typu for i in range(5): scroll() i liczy na szczęście.
To podejście jest zawodne. Pinterest ładuje nowe treści partiami po około 25 pinów, uruchamianymi przez zdarzenia przewijania. Jeśli przewiniesz pięć razy, możesz dostać 125 pinów — albo 75, jeśli sieć działa wolno, albo 150, jeśli partie są mniejsze. Potrzebujesz mądrzejszego wzorca.
Wzorzec „przewijaj, dopóki nie pojawią się nowe treści”
Oto solidna funkcja przewijania, która śledzi unikalne ID pinów, używa konfigurowalnego timeoutu, ma logikę ponowień i pokazuje postęp:
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" Przewinięcie {i+1}: {new_this_round} nowych pinów | {len(all_pins)} łącznie unikalnych pinów")
if len(all_pins) >= max_pins:
print(f" Osiągnięto limit max_pins ({max_pins}). Zatrzymuję.")
break
if new_this_round == 0:
no_new_count += 1
if no_new_count >= 3:
print(" Brak nowych pinów przez 3 kolejne przewinięcia. Koniec zawartości.")
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(" Wysokość strony bez zmian i brak nowych pinów. Prawdopodobnie koniec feedu.")
break
return all_pins
Dlaczego to działa:
- Usuwanie duplikatów po href: URL każdego pinu jest unikalny, więc używamy go jako identyfikatora. Zapobiega to liczeniu tego samego pinu dwa razy, gdy DOM renderuje się ponownie podczas przewijania.
- Reguła trzech prób: Jeśli trzy kolejne przewinięcia nic nie dają, kończymy. To pomaga w sytuacji, gdy strona jeszcze ładuje dane, ale nie ma już nowej zawartości.
- Losowe opóźnienie: Dodanie losowego opóźnienia 0,5–1,5 sekundy między przewinięciami sprawia, że zachowanie wygląda bardziej po ludzku i zmniejsza ryzyko wykrycia przez mechanizmy antybotowe.
- Limit bezpieczeństwa liczby przewinięć: Chroni przed nieskończoną pętlą, jeśli coś pójdzie nie tak.
Obsługa przypadków brzegowych
- Przerwanie przez „More Ideas”: Na stronach tablic Pinterest czasem wstawia sekcję „More Ideas”. Jeśli chcesz tylko faktyczne piny z tablicy, możesz wykryć ten element i zatrzymać przewijanie, gdy się pojawi.
- Ograniczanie szybkości przy długich sesjach: Jeśli przewijasz tablicę z tysiącami pinów, Pinterest może zacząć ograniczać odpowiedzi. Jeśli zauważysz, że co jakiś czas przewijanie nie przynosi nowych pinów (ale nie trzy razy z rzędu), zwiększ pauzę przewijania do 5+ sekund.
Jak pobierać obrazy z Pinteresta w pełnej rozdzielczości, a nie miniatury
To właśnie ten problem doprowadza ludzi do szału. Scrapujesz sporo pinów, pobierasz obrazy i wszystkie są maleńkimi miniaturami 236 px. Na forach opisuje się to jako „słaba jakość, za mały rozmiar”. Rozwiązanie polega na zrozumieniu struktury URL-i obrazów Pinteresta.
Jak działa ścieżka do obrazów na Pintereście
Wszystkie obrazy Pinteresta są serwowane z https://i.pinimg.com/{size}/{hash}.jpg. Segment {size} określa rozdzielczość:
| Ścieżka rozmiaru | Wymiary | Zastosowanie |
|---|---|---|
/236x/ | 236 px szerokości | Domyślny widok siatki (to, co dostajesz na start) |
/474x/ | 474 px szerokości | Średnia rozdzielczość |
/736x/ | 736 px szerokości | Widok szczegółów pinu / powiększony podgląd |
/originals/ | Oryginalne wymiary przesłania | Pełna rozdzielczość |
Funkcja pomocnicza: podbij dowolny URL obrazu Pinteresta do pełnej rozdzielczości
Oto funkcja, która przepisuje dowolny URL obrazu Pinteresta do najwyższej dostępnej jakości, z logiką awaryjną:
import requests as req
def upgrade_image_url(url, preferred_size="originals"):
"""Przepisuje URL obrazu Pinteresta na najwyższą dostępną rozdzielczość."""
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 # Zwracamy oryginał, jeśli wszystko zawiedzie
Ważna uwaga (stan na 2025 rok): ścieżka /originals/ coraz częściej zwraca błąd HTTP 403 Forbidden. Udokumentowany problem w gallery-dl potwierdza to zachowanie od połowy 2025 roku. Niezawodnym maksymalnym wariantem jest /736x/. Moja funkcja próbuje najpierw /originals/, a potem automatycznie przełącza się na /736x/.
Pobieranie obrazów do uporządkowanych folderów
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" Pobrano {filename} ({len(resp.content) // 1024} KB)")
else:
print(f" Nie udało się pobrać {filename}: HTTP {resp.status_code}")
except Exception as e:
print(f" Błąd pobierania {filename}: {e}")
time.sleep(delay + random.uniform(0.3, 0.8))
Dodaj opóźnienie między pobraniami. Ja używam 1,5–2,3 sekundy z losowym odchyleniem. Bez tego Pinterest po kilkuset żądaniach zacznie blokować Twój adres IP.
Eksport danych z Pinteresta
Eksport do CSV lub JSON
Podstawy omówiliśmy wcześniej. W przypadku większych zbiorów danych (10 000+ pinów) warto rozważyć format JSON Lines — jeden obiekt JSON w każdej linii — bo łatwiej go strumieniować i przetwarzać:
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")
Eksport do Google Sheets, Airtable lub Notion
Jeśli chcesz wysyłać dane bezpośrednio z Pythona do Google Sheets, potrzebujesz biblioteki gspread i konta serwisowego Google Cloud. Dla Airtable użyj pyairtable. Dla Notion — notion-client. Każde z tych rozwiązań wymaga konfiguracji API i znacząco zwiększa złożoność pipeline’u.
Albo — i tu jestem trochę stronniczy, ale to naprawdę najszybsza droga — możesz użyć Thunderbit, aby scrapować Pinteresta i wyeksportować dane do dowolnego z tych miejsc jednym kliknięciem. Bez kluczy API, bez kont serwisowych, bez dodatkowego kodu. Rozszerzenie Thunderbit do Chrome obsługuje eksport natywnie.
Jak uniknąć blokad podczas scrapowania Pinteresta
System antybotowy Pinteresta ma według ScrapeOps trudność obchodzenia ocenioną na [6/10] — nie jest banalny, ale też nie należy do najtrudniejszych. Wykorzystuje fingerprinting przeglądarki, analizę zachowania i limity oparte na IP. Oto co działa:
- Rotuj user agenty: używaj puli prawdziwych ciągów user agent Chrome i losuj jeden na sesję.
- Dodawaj losowe opóźnienia: 2–5 sekund między przewinięciami i żądaniami, z odchyleniem losowym. Bez proxy wydłuż do 10–15 sekund.
- Używaj realistycznego viewportu: ustaw
viewport={"width": 1920, "height": 1080}— nie używaj małych ani nietypowych wymiarów. - Rozważ proxy przy większej skali: jeśli scrapujesz tysiące pinów, rotuj proxy typu residential. Bez nich blokady IP są bardzo prawdopodobne po kilkuset żądaniach.
- Szanuj
robots.txt:robots.txtPinteresta blokuje większość crawlerów i zawiera około 180 reguł disallow. Warto mieć to na uwadze pod kątem zgodności. - Unikaj scrapowania po zalogowaniu: trzymaj się publicznie widocznych treści, gdy jesteś wylogowany. Scrapowanie za logowaniem zwiększa zarówno ryzyko prawne, jak i techniczne.
Thunderbit automatycznie radzi sobie z antybotami i CAPTCHA dzięki swojemu silnikowi AI — to jedna rzecz mniej do utrzymywania, jeśli wybierzesz opcję no-code.
Aspekty prawne i etyczne scrapowania Pinteresta
Skrócę ten fragment, bo nie jest głównym tematem artykułu, ale jest ważny.
Warunki korzystania z Pinteresta (sekcja 2a) mówią, że zgadzasz się nie „scrapować, zbierać, przeszukiwać, kopiować ani w inny sposób uzyskiwać dostępu do danych lub treści z Pinteresta w nieautoryzowany sposób, na przykład przy użyciu środków automatycznych (bez naszej uprzedniej wyraźnej zgody)”. Jednocześnie sądy w wielu przypadkach uznawały, że scrapowanie publicznie dostępnych danych nie narusza Computer Fraud and Abuse Act — zobacz hiQ v. LinkedIn oraz Meta v. Bright Data (styczeń 2024), gdzie sąd orzekł, że scrapowanie publicznie widocznych danych przy wylogowaniu jest legalne.
Kilka zasad podstawowych:
- Scrapuj wyłącznie publicznie widoczne treści i rób to po wylogowaniu
- Nie wykorzystuj danych ze scrapingu do spamu ani do podszywania się pod użytkowników
- Szanuj prawa autorskie do obrazów — jeśli to możliwe, pobieraj metadane i nie rozpowszechniaj komercyjnie chronionych obrazów bez zgody
- Jeśli planujesz używać danych ze scrapingu komercyjnie, skonsultuj się z prawnikiem
Jeśli chcesz głębiej wejść w temat, zobacz nasz przewodnik po skutkach prawnych web scrapingu.
Podsumowanie: czego się nauczyłeś i co dalej
Teraz już wiesz, dlaczego statyczny scraping zawodzi na Pintereście (to aplikacja SPA w React — brak JavaScriptu, brak danych), jak używać Playwright do scrapowania wyników wyszukiwania, tablic i profili użytkowników, jak zbudować produkcyjny handler nieskończonego przewijania, który nie kończy pracy po 16 pinach, oraz jak pobierać obrazy w pełnej rozdzielczości zamiast malutkich miniaturek.
Krótka powtórka najważniejszych rzeczy:
requests+ BeautifulSoup nie zadziała na Pintereście. Nie trać na to czasu.- Playwright to najlepsze narzędzie w Pythonie do tego zadania — szybkie, dobrze wspierane i natywnie obsługujące renderowanie JS.
- Nieskończone przewijanie wymaga pętli opartej na usuwaniu duplikatów, a nie stałej liczby przewinięć.
- Obrazy w pełnej rozdzielczości wymagają przepisywania ścieżki URL — celuj w
/736x/(bo/originals/często zwraca 403). - Scraping tablic i profili jest słabo opisany w istniejących poradnikach, ale z odpowiednimi selektorami jest całkiem prosty.
- Dla osób nietechnicznych i zespołów, którym zależy na szybkości, Thunderbit pozwala scrapować Pinteresta w 2 kliknięcia i eksportować dane do Google Sheets, Excela, Airtable albo Notion — bez Pythona. Wypróbuj za darmo przez rozszerzenie Chrome.
Jeśli budujesz pipeline w Pythonie, kod z tego poradnika daje Ci solidny fundament. Jeśli po prostu potrzebujesz danych, Thunderbit jest skrótem. W obu przypadkach nie utkniesz już z 16 pinami i pustym spojrzeniem.
Więcej o scrapowaniu i ekstrakcji danych znajdziesz w naszych poradnikach: jak scrapować strony internetowe w Pythonie, najlepsze automatyczne narzędzia do web scrapingu oraz jak pobierać dane ze strony do Excela. Możesz też sprawdzić cennik Thunderbit albo obejrzeć materiały na kanale Thunderbit na YouTube.
FAQ
1. Czy da się scrapować Pinteresta przy użyciu BeautifulSoup?
Nie skutecznie samym BeautifulSoup. Pinterest renderuje całą treść przez JavaScript, więc requests + BeautifulSoup widzi tylko pusty szkielet HTML. Najpierw potrzebujesz headless browsera, takiego jak Playwright lub Selenium, który wyrenderuje stronę, albo możesz użyć narzędzia no-code, takiego jak Thunderbit, które automatycznie obsługuje renderowanie JS.
2. Ile pinów można pobrać z Pinteresta w jednej sesji?
To zależy od logiki przewijania i obsługi antybota. Przy produkcyjnym handlerze nieskończonego przewijania z tego poradnika (deduplikacja, timeout, retry) możesz niezawodnie pobierać od setek do tysięcy pinów na tablicę albo na zapytanie wyszukiwania. W przypadku bardzo dużych tablic licz się z kilkoma minutami przewijania i zbierania danych.
3. Dlaczego pobrane obrazy z Pinteresta są takie małe?
Domyślnie Pinterest serwuje miniatury /236x/ w widoku siatki. Aby uzyskać wyższą rozdzielczość, przepisz ścieżkę URL obrazu na /736x/ albo /originals/. Pamiętaj jednak, że /originals/ coraz częściej zwraca błędy 403 w 2025 roku, więc /736x/ to najbardziej niezawodny maksymalny wariant.
4. Czy scrapowanie Pinteresta jest legalne?
Scraping publicznie dostępnych danych jest generalnie akceptowany na podstawie nowszych orzeczeń sądowych (np. hiQ v. LinkedIn, Meta v. Bright Data), ale regulamin Pinteresta zabrania nieautoryzowanego, automatycznego dostępu. Trzymaj się treści publicznych, nie używaj danych do spamu, szanuj prawa autorskie i skonsultuj zastosowania komercyjne z prawnikiem.
5. Jaka jest najlepsza alternatywa no-code do scrapowania Pinteresta?
Thunderbit AI Web Scraper potrafi wyciągać dane pinów z Pinteresta — tytuły, obrazy, URL-e, opisy — w 2 kliknięcia, z wbudowanym eksportem do Google Sheets, Excela, Airtable albo Notion. Obsługuje renderowanie JavaScriptu, nieskończone przewijanie i mechanizmy antybotowe automatycznie, więc nie musisz pisać ani utrzymywać kodu.
Dowiedz się więcej


