Python Pinterest 爬蟲:『Pins、Boards 與無限捲動』

最後更新於 April 17, 2026

幾個月前,我們其中一位工程師在週末寫好了一支 Python 腳本,拿給我看。它原本是要替一個市場研究專案,從 Pinterest 抓取產品靈感圖片。結果他一跑,抓到的只有……16 個 pin。明明那個 board 裡有超過 2,000 個。她盯著螢幕看了一會兒,又看看我,然後說:「我覺得 Pinterest 在嘲笑我。」

這種情況並不罕見。這幾乎是我看過最多開發者在用 Python 抓 Pinterest 時遇到的挫折。你打開 requests 和 BeautifulSoup,丟一個 Pinterest URL 進去,結果只拿回零星幾筆資料,甚至只是一個空白的 HTML 骨架。原因很簡單:Pinterest 是完全由 JavaScript 渲染的單頁應用程式,單純的 HTTP 請求根本看不到真正內容。在這篇指南裡,我會帶你了解為什麼會這樣、哪些方法真的有效(Playwright、攔截內部 API,以及像 這類免程式工具),並提供逐步程式碼,教你抓取 pins、boards、使用者檔案、無限捲動內容,以及高解析度圖片。不管你是想打造可上線的爬蟲,還是只是想快速抓資料,這篇文章都能幫上忙。

什麼是 Pinterest 爬蟲?

Pinterest 爬蟲是透過程式化方式從 Pinterest 擷取資料的流程,例如 pin 圖片、標題、描述、board 名稱、粉絲數與 URL。你不需要一張張手動瀏覽與儲存 pins,而是用程式(或工具)從搜尋結果、boards 或使用者檔案中大規模收集結構化資料。

截至 2025 年底,Pinterest 平台上已有,每月活躍用戶達,是網路上最豐富的視覺資料來源之一。對企業來說,這些資料非常有價值——不管你是在追蹤產品趨勢、比較競品內容,還是建立網紅合作名單。

為什麼要用 Python 抓 Pinterest?

Pinterest 早就不只是婚禮籌備用的靈感牆了。它其實是一個很有價值的商業情報平台——曾因品牌 Pins 買過東西,而,代表使用者有明確意圖,但未必已有品牌偏好。這對發現新機會來說非常重要,也解釋了為什麼這麼多團隊都想拿到結構化的 Pinterest 資料。

以下是不同團隊可能會需要的資料:

團隊需要的資料商業價值
電商營運商品圖片、價格、流行風格競爭性定價、依趨勢調整庫存
行銷Board 表現、pin 互動、競品內容內容策略、活動基準比較
業務 / 開發名單創作者檔案、粉絲數、聯絡資訊網紅開發、合作對象鎖定
房地產居家佈置 pins、裝潢趨勢、空間配置房源攝影、佈置建議
內容創作者熱門主題、流行格式、季節性題材內容行事曆、視覺風格研究

更關鍵的是:Pinterest 官方 API 的限制很多。你需要商業帳號、審核(甚至包含應用程式的影片示範),而且只能存取你自己的帳號資料。如果你想瀏覽公開 boards、搜尋結果或競品檔案,爬蟲才是實際可行的替代方案。這也是為什麼很多團隊會選擇 Python——或者在想省掉設定時,直接改用像 Thunderbit 這樣的免程式工具。

為什麼只用 BeautifulSoup 會在 Pinterest 上失敗(以及真正有效的方法)

如果你曾經用 requests + BeautifulSoup 抓 Pinterest,卻只拿到 16 筆資料或空白頁面,那不是你的錯覺。Pinterest 是用 React 打造的,所有內容都透過 JavaScript 動態渲染。當你用一般 HTTP 請求抓 Pinterest URL 時,伺服器只會回傳最小化的 HTML 骨架——幾個 <link><script> 標籤,以及 React 要掛載應用程式的空白 <div>。所有 pin 卡片、圖片、標題與網格排版,都是瀏覽器執行 JavaScript 後才注入的。

沒有 JavaScript 執行,就沒有 pins。

那到底什麼方法有效?以下是幾種主要方案的比較:

方法支援 JavaScript?能取得完整資料?複雜度適合用途
requests + BeautifulSoup約 0–16 筆不適合 Pinterest
Selenium / Playwright是,需處理捲動完整控制、Python 流程
攔截 Pinterest 內部 API是,分頁 JSON最大化資料量,不需瀏覽器
第三方 Scraper API依服務而定不想自建基礎架構的規模化需求
免程式工具(Thunderbit)AI 結構化很低非技術使用者、快速取得結果

這篇教學我會推薦用 Playwright 作為 Python 方案。它可以渲染 JavaScript、支援模擬捲動、維護良好(GitHub 上有,且在職缺中的成長率達),而且在效能測試上比 Selenium 快上。如果你想走免程式路線,我也會一起介紹。

Pinterest 官方 API vs. Python 爬蟲 vs. 免程式工具:該選哪條路?

在你開始寫程式前,先問自己:真的需要自己寫嗎?以下是決策參考:

評估項目Pinterest APIPython 爬蟲Thunderbit(免程式)
需要審核商業帳號 + 影片示範不需要不需要
可存取公開 pins/boards有限(僅自己的資料)完整完整
可下載高解析度圖片依情況而定可以,透過 URL 解析可以,透過圖片擷取
支援無限捲動不適用可以,需寫程式自動處理
維護成本高(selector 容易失效)幾乎沒有(AI 自動調整)
匯出到 Sheets/Airtable手動自行撰寫程式內建支援
設定時間幾小時到幾天30–60 分鐘2 分鐘

如果你是行銷、電商營運,或任何只想把 Pinterest 資料放進試算表、又不想寫或維護 Python 腳本的人, 會是最快的路。你只要打開任何 Pinterest 頁面,點選「AI Suggest Fields」,再按「Scrape」,就能直接匯出到 Google Sheets、Excel、Airtable 或 Notion。它的子頁面擷取功能甚至可以自動追蹤單一 pin 的連結來補齊資料。我看過完全沒寫過程式的人,在三分鐘內把 500 多個 pins 匯入 Google Sheet。

如果你想要完全掌控流程、想把爬蟲整合進 Python pipeline,或單純喜歡自己動手打造工具,那就繼續看下去。

建立 Pinterest 爬蟲的 Python 環境

  • 難度: 中等
  • 所需時間: 約 30–60 分鐘(含撰寫與測試)
  • 你需要準備: Python 3.9+、Chrome 瀏覽器(用於測試)、終端機 / 命令列存取權限

安裝 Playwright 與相依套件

先建立專案資料夾並設定虛擬環境:

1mkdir pinterest-scraper
2cd pinterest-scraper
3python -m venv venv
4source venv/bin/activate  # On Windows: venv\Scripts\activate

安裝 Playwright 並下載 Chromium 瀏覽器執行檔:

1pip install playwright
2playwright install chromium

你也會用到 Python 內建的 jsonoscsv 模組來匯出資料,這些不需要額外安裝。

專案資料夾結構

我建議一開始就把架構整理好:

1pinterest-scraper/
2├── scraper.py
3├── config.py
4├── output/
5│   ├── pins.json
6│   └── pins.csv
7└── images/
8    ├── board-name-1/
9    └── board-name-2/

config.py 裡設定你的 user agent 字串。Pinterest 會阻擋預設的無頭瀏覽器識別字串,所以要用更接近真實瀏覽器的版本:

1USER_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

把查詢字串塞進網址範本中:

1query = "mid century modern furniture"
2url = f"https://www.pinterest.com/search/pins/?q={query.replace(' ', '%20')}&rs=typed"

你可以把它參數化,套用到任何搜尋詞。rs=typed 這個參數會告訴 Pinterest,這個查詢是手動輸入的(不是建議詞),有時會影響結果相關性。

步驟 2:啟動無頭瀏覽器並載入頁面

下面是核心的 Playwright 設定。注意自訂 user agent——如果沒有它,Pinterest 很可能會封鎖你,或直接顯示登入牆。

1import asyncio
2from playwright.async_api import async_playwright
3from config import USER_AGENT
4async def scrape_search(query, max_pins=100):
5    url = f"https://www.pinterest.com/search/pins/?q={query.replace(' ', '%20')}&rs=typed"
6    async with async_playwright() as p:
7        browser = await p.chromium.launch(headless=True)
8        page = await browser.new_page(
9            user_agent=USER_AGENT,
10            viewport={"width": 1920, "height": 1080}
11        )
12        await page.goto(url)
13        await asyncio.sleep(3)  # 等待 JavaScript 渲染初始 pins

執行完後,頁面應該會載入第一批 pins,通常約 25–50 個。

步驟 3:從頁面擷取 pin 資料

Pinterest 會把每個 pin 包在 div[data-test-id='pinWrapper'] 裡。裡面會有一個連結(<a>),包含 pin 的 URL 和標題(透過 aria-label),以及一個 <img>,裡面有縮圖 URL。

1        results = []
2        pins = await page.query_selector_all("div[data-test-id='pinWrapper']")
3        for pin in pins:
4            link = await pin.query_selector("a")
5            if not link:
6                continue
7            title = await link.get_attribute("aria-label") or ""
8            href = await link.get_attribute("href") or ""
9            img = await pin.query_selector("img")
10            src = await img.get_attribute("src") if img else ""
11            results.append({
12                "title": title,
13                "url": f"https://www.pinterest.com{href}" if href.startswith("/") else href,
14                "image_url": src
15            })

此時 results 只包含初始畫面上看得到的 pins。若要取得更多,就需要捲動——這也是最重要的部分。

步驟 4:將結果儲存成 JSON 或 CSV

擷取完成後,把資料寫入檔案,方便後續使用:

1import json
2import csv
3def save_json(data, filepath="output/pins.json"):
4    with open(filepath, "w", encoding="utf-8") as f:
5        json.dump(data, f, ensure_ascii=False, indent=2)
6def save_csv(data, filepath="output/pins.csv"):
7    if not data:
8        return
9    with open(filepath, "w", newline="", encoding="utf-8-sig") as f:
10        writer = csv.DictWriter(f, fieldnames=data[0].keys())
11        writer.writeheader()
12        writer.writerows(data)

如果你打算用 Excel 開啟 CSV,建議使用 utf-8-sig 編碼,這樣可以避免亂碼。

擷取整個 Pinterest Board 與使用者檔案

這是現有教學裡很大的缺口。我幾乎找不到任何競品文章會深入講 board 或 profile 的擷取,但這卻是論壇裡最常被問到的功能之一。大家想下載某個 board 的全部 pins、把圖片依 board 分資料夾,還想抓取使用者檔案層級的資料,例如粉絲數與 board 清單。

從 Board URL 擷取所有 Pins

Board URL 通常長這樣:https://www.pinterest.com/{username}/{board-name}/。DOM 結構和搜尋結果類似——pins 一樣包在 div[data-test-id='pinWrapper'] 裡——但你需要捲動才能把它們全部載入。

1async def scrape_board(board_url, max_pins=500):
2    async with async_playwright() as p:
3        browser = await p.chromium.launch(headless=True)
4        page = await browser.new_page(user_agent=USER_AGENT, viewport={"width": 1920, "height": 1080})
5        await page.goto(board_url)
6        await asyncio.sleep(3)
7        seen_ids = set()
8        all_pins = []
9        for scroll_round in range(100):  # 安全上限
10            pins = await page.query_selector_all("div[data-test-id='pinWrapper']")
11            new_count = 0
12            for pin in pins:
13                link = await pin.query_selector("a")
14                if not link:
15                    continue
16                href = await link.get_attribute("href") or ""
17                if href in seen_ids:
18                    continue
19                seen_ids.add(href)
20                new_count += 1
21                title = await link.get_attribute("aria-label") or ""
22                img = await link.query_selector("img")
23                src = await img.get_attribute("src") if img else ""
24                all_pins.append({
25                    "title": title,
26                    "url": f"https://www.pinterest.com{href}" if href.startswith("/") else href,
27                    "image_url": src
28                })
29            print(f"Scroll {scroll_round + 1}: 已收集 {len(all_pins)} 個唯一 pins")
30            if new_count == 0 or len(all_pins) >= max_pins:
31                break
32            prev_height = await page.evaluate("document.body.scrollHeight")
33            await page.evaluate("window.scrollTo(0, document.body.scrollHeight)")
34            await asyncio.sleep(2.5)
35            curr_height = await page.evaluate("document.body.scrollHeight")
36            if curr_height == prev_height:
37                break  # 沒有更多內容
38        await browser.close()
39        return all_pins

要注意的一點是:board 頁面有時會出現一個「More Ideas」分頁,把已儲存的 pins 和演算法推薦內容分開。如果你只想抓使用者實際儲存的 pins,那麼當你碰到那個分隔區塊時,就可以停止捲動。

擷取使用者檔案:boards、粉絲數與 pins

Profile URL 長這樣:https://www.pinterest.com/{username}/。從 profile 頁面可以擷取:

  • 粉絲 / 追蹤中數量:div[data-test-id='follower-count']
  • Board 清單: 每個 board 都是一張卡片,連到 /{username}/{board-name}/
  • 總 pins 數: 有時會顯示在 profile 標頭中
1async def scrape_profile(username):
2    url = f"https://www.pinterest.com/{username}/"
3    async with async_playwright() as p:
4        browser = await p.chromium.launch(headless=True)
5        page = await browser.new_page(user_agent=USER_AGENT, viewport={"width": 1920, "height": 1080})
6        await page.goto(url)
7        await asyncio.sleep(3)
8        # 擷取粉絲數
9        follower_el = await page.query_selector("div[data-test-id='follower-count']")
10        followers = await follower_el.inner_text() if follower_el else "N/A"
11        # 擷取 board 連結
12        board_links = await page.query_selector_all("a[href*='/" + username + "/']")
13        boards = []
14        for bl in board_links:
15            href = await bl.get_attribute("href") or ""
16            name = await bl.get_attribute("aria-label") or href.split("/")[-2]
17            if href.count("/") >= 3 and href != f"/{username}/":
18                boards.append({"name": name, "url": f"https://www.pinterest.com{href}"})
19        await browser.close()
20        return {"username": username, "followers": followers, "boards": boards}

如果你想抓取某個 profile 底下所有 board 的 pins,可以把 board 清單迴圈跑一遍,對每個 board 呼叫 scrape_board()。你也可以自動把下載的圖片整理到各自的 board 資料夾中。

建立可上線使用的無限捲動處理器

這個部分決定了一支腳本是玩具還是真正可用的爬蟲。最常見的痛點——我在至少十幾個論壇討論串裡都看過——就是爬蟲只抓到 16–25 筆資料,原因不是它不會跑,而是它沒有捲得夠遠,或只是寫了固定次數的 for i in range(5): scroll() 然後祈禱它成功。

這種寫法不可靠。Pinterest 會在捲動事件觸發時,以大約 25 個 pin 為一批載入新內容。你捲五次,可能拿到 125 個 pins,也可能因為網路較慢只拿到 75 個,甚至只有 150 個,視批次大小而定。你需要更聰明的做法。

滾動直到沒有新內容的模式

以下是一個更穩健的捲動函式,它會追蹤唯一的 pin ID、使用可調整的 timeout、加入重試邏輯,並顯示進度:

1import time
2import random
3async def scroll_and_collect(page, max_pins=1000, max_scrolls=200, scroll_pause=2.5):
4    seen_ids = set()
5    all_pins = []
6    no_new_count = 0
7    for i in range(max_scrolls):
8        pins = await page.query_selector_all("div[data-test-id='pinWrapper']")
9        new_this_round = 0
10        for pin in pins:
11            link = await pin.query_selector("a")
12            if not link:
13                continue
14            href = await link.get_attribute("href") or ""
15            if href in seen_ids:
16                continue
17            seen_ids.add(href)
18            new_this_round += 1
19            title = await link.get_attribute("aria-label") or ""
20            img = await link.query_selector("img")
21            src = await img.get_attribute("src") if img else ""
22            all_pins.append({
23                "title": title,
24                "url": f"https://www.pinterest.com{href}" if href.startswith("/") else href,
25                "image_url": src
26            })
27        print(f"  第 {i+1} 次捲動:{new_this_round} 個新 pins|共 {len(all_pins)} 個唯一 pins")
28        if len(all_pins) >= max_pins:
29            print(f"  已達到 max_pins 上限({max_pins})。停止。")
30            break
31        if new_this_round == 0:
32            no_new_count += 1
33            if no_new_count >= 3:
34                print("  連續 3 次捲動都沒有新 pins。內容已到底。")
35                break
36        else:
37            no_new_count = 0
38        prev_height = await page.evaluate("document.body.scrollHeight")
39        await page.evaluate("window.scrollTo(0, document.body.scrollHeight)")
40        await asyncio.sleep(scroll_pause + random.uniform(0.5, 1.5))
41        curr_height = await page.evaluate("document.body.scrollHeight")
42        if curr_height == prev_height and new_this_round == 0:
43            print("  頁面高度未變,且沒有新 pins。很可能已經到底。")
44            break
45    return all_pins

為什麼這個設計有效:

  • 依 href 去重: 每個 pin 的 URL 都是唯一的,所以我們把它當作 ID 使用。這可以避免在捲動期間 DOM 重新渲染時,重複計算同一個 pin。
  • 三次無新增就停止: 如果連續三次捲動都沒有新資料,就停止。這能處理頁面還在載入、但其實已經沒有新內容的情況。
  • 加入隨機抖動: 在每次捲動之間加入 0.5–1.5 秒的隨機延遲,行為會更接近真人,也能降低觸發反爬機制的機率。
  • 最大捲動次數保護: 避免因為程式錯誤而陷入無限迴圈。

處理特殊狀況

  • 「More Ideas」中斷: 在 board 頁面裡,Pinterest 有時會插入一個「More Ideas」區塊。如果你只想抓這個 board 真正儲存的 pins,可以偵測到這個元素後停止捲動。
  • 長時間操作的限流: 如果你正在捲動一個有上千個 pins 的 board,Pinterest 可能會開始限制回應速度。若你發現捲動有時候會抓不到新資料(但不是連續三次),把 scroll_pause 調整到 5 秒以上。

取得 Pinterest 的完整解析度圖片(不是縮圖)

這點最容易讓人抓狂。你抓了一堆 pins,把圖片下載下來,結果全都是 236px 的小縮圖。論壇使用者常把它形容成「品質很糟,尺寸太小」。解法就是了解 Pinterest 的圖片 URL 結構。

了解 Pinterest 圖片 URL 路徑

Pinterest 的圖片都由 https://i.pinimg.com/{size}/{hash}.jpg 提供服務。{size} 這個區段決定解析度:

尺寸路徑圖片尺寸用途
/236x/寬 236px預設網格檢視(你最常拿到的版本)
/474x/寬 474px中等解析度
/736x/寬 736pxpin 詳細頁 / 展開檢視
/originals/原始上傳尺寸完整解析度

工具函式:將任何 Pinterest 圖片 URL 升級到高解析度

下面這個函式會把任何 Pinterest 圖片 URL 改寫成可用的最高畫質,並附帶 fallback 邏輯:

1import requests as req
2def upgrade_image_url(url, preferred_size="originals"):
3    """將 Pinterest 圖片 URL 改寫為最高可用解析度。"""
4    sizes = ["originals", "736x", "474x", "236x"]
5    if preferred_size not in sizes:
6        preferred_size = "originals"
7    for size in sizes[sizes.index(preferred_size):]:
8        upgraded = url
9        for s in sizes:
10            upgraded = upgraded.replace(f"/{s}/", f"/{size}/")
11        try:
12            resp = req.head(upgraded, timeout=5, allow_redirects=True)
13            if resp.status_code == 200:
14                return upgraded
15        except Exception:
16            continue
17    return url  # 如果都失敗,就回傳原始網址

重要提醒(截至 2025 年): /originals/ 路徑越來越常回傳 HTTP 403 Forbidden。gallery-dl 的也證實了這個行為在 2025 年中期依然存在。實務上最可靠的最高解析度通常是 /736x/。我的函式會先嘗試 /originals/,失敗後自動改用 /736x/

將圖片下載到有整理的資料夾

1import os
2import time
3def download_images(pins, folder="images/default", delay=1.5):
4    os.makedirs(folder, exist_ok=True)
5    for i, pin in enumerate(pins):
6        img_url = upgrade_image_url(pin.get("image_url", ""), preferred_size="736x")
7        if not img_url:
8            continue
9        filename = f"pin_{i+1}.jpg"
10        filepath = os.path.join(folder, filename)
11        try:
12            resp = req.get(img_url, timeout=15)
13            if resp.status_code == 200:
14                with open(filepath, "wb") as f:
15                    f.write(resp.content)
16                print(f"  已下載 {filename}{len(resp.content) // 1024} KB)")
17            else:
18                print(f"  {filename} 下載失敗:HTTP {resp.status_code}")
19        except Exception as e:
20            print(f"  下載 {filename} 時發生錯誤:{e}")
21        time.sleep(delay + random.uniform(0.3, 0.8))

下載之間記得加上節流延遲。我通常會使用 1.5–2.3 秒,並加上隨機抖動。如果不這樣做,Pinterest 幾百次請求後就可能封鎖你的 IP。

匯出你抓到的 Pinterest 資料

匯出成 CSV 或 JSON

前面我們已經說過基本做法。如果資料量很大(10,000+ 個 pins),可以考慮 JSON Lines 格式——每行一個 JSON 物件——這樣更容易串流與處理:

1def save_jsonl(data, filepath="output/pins.jsonl"):
2    with open(filepath, "w", encoding="utf-8") as f:
3        for item in data:
4            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 設定,而且會讓整條流程變得更複雜。

或者——雖然我有點偏心,但這真的是最快的方法——你也可以用 直接抓 Pinterest,然後一鍵匯出到這些目的地。沒有 API keys,沒有 service account,也不用額外寫程式。 可以原生處理匯出。

如何避免在抓 Pinterest 時被封鎖

ScrapeOps 將 Pinterest 的反機器人系統評為——不算簡單,但也不是最難對付的目標。它會使用瀏覽器指紋辨識、行為分析與基於 IP 的限流。以下做法比較有效:

  • 輪換 user agent: 準備一組真實 Chrome user agent 字串,每次 session 隨機選一個。
  • 加入隨機延遲: 捲動與請求之間加入 2–5 秒的等待,並帶些隨機抖動。如果沒有代理,則建議拉長到 10–15 秒。
  • 使用合理的視窗大小: 設定 viewport={"width": 1920, "height": 1080},不要用太小或奇怪的尺寸。
  • 大規模作業請考慮代理: 如果你要抓幾千個 pins,建議使用住宅代理輪換。沒有代理的話,幾百次請求後就可能被封。
  • 注意 robots.txt Pinterest 的 robots.txt 封鎖了大多數自動爬蟲,且有。做合規評估時要留意。
  • 避免登入後爬取: 盡量只抓登入狀態下可直接看到的公開內容。登入後抓取會帶來法律與技術風險。

如果你走免程式路線,Thunderbit 的 AI 引擎會自動處理反機器人與 CAPTCHA 挑戰,讓你少維護一大堆東西。

Pinterest 爬蟲的法律與倫理考量

這部分我會簡短帶過,因為不是本文重點,但它很重要。

Pinterest 的服務條款(第 2a 條)指出,你同意不會以未經授權的方式「scrape、collect、search、copy 或以其他方式存取 Pinterest 的資料或內容」,例如使用自動化方式(且未事先取得我們明確許可)。儘管如此,法院通常認為,抓取公開可得資料並不違反 Computer Fraud and Abuse Act——可參考 以及 Meta v. Bright Data(2024 年 1 月),該案中法院裁定,在登出狀態下抓取公開可見資料是合法的。

幾個基本原則:

  • 只抓取登出狀態下可公開瀏覽的內容
  • 不要把抓來的資料用於垃圾訊息或冒充使用者
  • 尊重圖片著作權——盡可能只擷取中繼資料,未經許可不要商業性重發受著作權保護的圖片
  • 如果你打算把資料用於商業用途,請先諮詢律師

如果你想更深入了解法律面,請參考我們的

結語:你學到了什麼,以及下一步該做什麼

現在你已經知道為什麼靜態爬取在 Pinterest 上會失敗(它是 React SPA——沒有 JavaScript,就沒有資料)、如何用 Playwright 抓搜尋結果、boards 和使用者檔案、如何建立一個能撐住實戰的無限捲動處理器,不會只抓到 16 個 pin 就停下來,以及如何拿到高解析度圖片,而不是小縮圖。

重點快速回顧:

  • requests + BeautifulSoup 在 Pinterest 上行不通,別浪費時間。
  • Playwright 是這項工作的最佳 Python 工具——速度快、支援完善,且能原生處理 JavaScript 渲染。
  • 無限捲動 需要的是基於去重的捲動迴圈,而不是固定次數。
  • 高解析度圖片 需要改寫 URL 路徑——請優先使用 /736x/(因為 /originals/ 經常回傳 403)。
  • Board 與 profile 擷取 在現有教學中比較少被談到,但只要 selector 正確,其實不難。
  • 如果你不想寫程式,或只想要快, 讓你 2 下點擊就能抓 Pinterest,並匯出到 Google Sheets、Excel、Airtable 或 Notion——完全不需要 Python。你可以透過 免費試用。

如果你正在打造 Python pipeline,本指南中的程式碼能提供穩固基礎。如果你只是需要資料,Thunderbit 會是更快的捷徑。不管哪種方式,你都不必再卡在只抓到 16 個 pin、對著空白螢幕發呆了。

想了解更多關於爬蟲與資料擷取的內容,歡迎參考我們的指南:、以及。你也可以查看 ,或到 看教學影片。

常見問題

1. 可以只用 BeautifulSoup 抓 Pinterest 嗎?

單獨使用效果並不好。Pinterest 的所有內容都是透過 JavaScript 渲染,所以 requests + BeautifulSoup 只會看到空的 HTML 骨架。你需要先用 Playwright 或 Selenium 這類無頭瀏覽器把頁面渲染出來,或者直接用像 Thunderbit 這種會自動處理 JavaScript 渲染的免程式工具。

2. 一次 session 可以從 Pinterest 抓多少個 pins?

這取決於你的捲動邏輯與反機器人處理方式。使用本文的可上線無限捲動處理器(去重、timeout、重試邏輯)時,每個 board 或搜尋字詞通常可以穩定抓到數百到數千個 pins。若 board 很大,捲動與收集可能需要幾分鐘。

3. 為什麼我抓到的 Pinterest 圖片都很小?

預設情況下,Pinterest 在網格視圖中會提供 /236x/ 縮圖。若要更高解析度,請把圖片 URL 路徑改成 /736x//originals/。不過截至 2025 年,/originals/ 越來越常回傳 403,因此 /736x/ 才是比較可靠的最高版本。

4. 抓 Pinterest 合法嗎?

根據近期法院判決(例如 hiQ v. LinkedIn、Meta v. Bright Data),抓取公開可得資料通常是被接受的,但 Pinterest 的服務條款禁止未經授權的自動化存取。請僅限公開內容,不要把資料用於垃圾訊息,尊重著作權,若是商業用途則請先諮詢法律專業人士。

5. 抓 Pinterest 最好的免程式替代方案是什麼?

可以在 2 次點擊內擷取 Pinterest pin 資料——包含標題、圖片、URL、描述——並內建匯出到 Google Sheets、Excel、Airtable 或 Notion。它會自動處理 JavaScript 渲染、無限捲動與反機器人挑戰,所以你完全不需要寫或維護任何程式。

了解更多

Shuai Guan
Shuai Guan
Co-founder/CEO @ Thunderbit. Passionate about cross section of AI and Automation. He's a big advocate of automation and loves making it more accessible to everyone. Beyond tech, he channels his creativity through a passion for photography, capturing stories one picture at a time.
目錄

試試 Thunderbit

只要 2 次點擊,就能抓取潛在客戶與其他資料。AI 驅動。

取得 Thunderbit 免費使用
用 AI 擷取資料
輕鬆將資料轉移到 Google Sheets、Airtable 或 Notion
Chrome Store Rating
PRODUCT HUNT#1 Product of the Week