用 Python 自動化市場研究:抓取 Shopify 資料

最後更新於 April 16, 2026

Shopify 的 /products.json 端點可以說是電商資料圈裡大家都知道的「神兵利器」。只要在任何 Shopify 商店網址後面接上它,就能直接拿到結構化 JSON——不用 API 金鑰、不用驗證,也不用在一層又一層的 HTML 裡東翻西找。

我在 團隊工作,所以平常很常在想大家要怎麼從網路上擷取資料。Shopify 抓取這件事也常被提到——像是銷售團隊追蹤競品價格、電商營運人員比較商品目錄、採購人員找新供應商。Shopify 目前有 ,而且平台大約佔美國電商市場的 ,能抓到的商品資料量真的很驚人。

這篇指南會完整帶你走一遍流程:端點會回傳什麼、怎麼分頁抓取數千個商品、如何在不被封鎖的前提下處理速率限制,以及怎麼用 pandas 把 Shopify 的巢狀 JSON 攤平成乾淨的 CSV 或 Excel 檔。我也會介紹其他文章比較少提到的端點(/collections.json/meta.json),最後再提供一個免寫程式的替代方案,給想直接跳過 Python 的人。

Shopify 的 /products.json 端點是什麼?為什麼它讓抓取變得這麼簡單?

每個 Shopify 商店都有一個公開端點 {store-url}/products.json,會回傳結構化的商品資料。沒有 API 金鑰、沒有 OAuth、也不用任何驗證。你只要把 /products.json 接到商店網址後面,就能拿到整個商品目錄的 JSON 陣列。

你現在就可以自己試試看:在瀏覽器打開 。你會看到乾淨、結構清楚的 JSON,裡面包含商品標題、價格、變體、圖片、標籤等資訊。

跟另一種做法比起來差異就很明顯:解析 Shopify 的 HTML 主題頁面,通常結構一層包一層、不同商店的格式也不一樣,而且商家只要一更新主題,整個結構就可能變掉。你要處理的會是這種東西:

HTML 做法(很痛苦):

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

JSON 做法(很乾淨):

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

在一致性、穩定性和解析難度上,JSON 都明顯更有優勢。這個端點也支援兩個重要查詢參數——?limit=(每頁最多 250 筆商品,預設是 30)與 ?page=(分頁)——後面的範例會大量用到。

要注意的是:這是 公開的商店前台端點,不是 。Admin API 需要商店擁有者的存取權杖,可以拿到訂單資料、庫存量和客戶資訊;而公開的 /products.json 只能讀取商品資料,任何人都能存取。這兩者差很多,因為很多論壇討論常常把它們混在一起。

補充注意:不是每個 Shopify 商店都會開放這個端點。根據我的測試,大約有 71% 的商店會回傳有效 JSON(像 allbirds.com、gymshark.com、colourpop.com、kyliecosmetics.com 都可以),但也有一些自訂設定的商店會回 404(例如 hiutdenim.co.uk、bombas.com)。最簡單的檢查方式就是:直接在瀏覽器打開 {store-url}/products.json 看看結果。

為什麼要用 Python 抓 Shopify?常見商業應用場景

為什麼值得做?因為投資報酬率很高。現在都會用自動化價格抓取來做競爭情報分析,遠高於 2020 年的 34%。研究也顯示,。這些資料真的很有價值。

以下是我最常看到的應用情境:

應用場景受益對象你能得到什麼
競品價格監控電商營運團隊追蹤競品目錄中的價格變動、折扣與比價價格
商品研究與採購採購/商品企劃比較商品特色、變體、材質與庫存可得性
名單開發業務團隊從商店目錄擷取供應商名稱、品牌資料與聯絡資訊
市場與品類分析行銷團隊了解商品組合、標籤、集合分類結構與定位
庫存與供應狀態追蹤供應鏈團隊監控變體層級的庫存狀態(available: true/false)
新品偵測產品團隊追蹤 created_at 時間戳,找出競品新品上架時間

Python 是做這件事的自然選擇。都把 Python 當作主要語言,而 requests 負責 HTTP、pandas 處理資料、httpx 可以做非同步,讓你能在 80 行以內的程式碼中,從「我有一個網址」一路做到「我有一份試算表」。

完整的 products.json 欄位參考:每個欄位都幫你拆解好

很多教學只會展示 titleidhandle,然後就草草帶過。但 Shopify 的 JSON 回應其實包含 40 多個跨商品、變體、圖片與選項的欄位。先了解有哪些欄位,再開始寫抓取程式,能省下之後重抓的麻煩。

我整理這份參考表,是根據 2026 年 4 月 16 日實際抓取的 /products.json 回應。只要端點有開放,所有商店的結構都一樣。

商品層級欄位

欄位資料類型範例值商業用途
id整數123456789商品唯一識別碼,用於去重
title字串"Classic Blue Jeans"商品名稱,用於目錄與比對
handle字串"classic-blue-jeans"URL slug,可組成商品頁連結 {store}/products/{handle}
body_html字串(HTML)或 null

Our best-selling...

商品描述,可用於內容分析與 SEO 研究
vendor字串"Hiut Denim"品牌/供應商名稱,用於開發名單或採購
product_type字串"Jeans"品類分類,用於市場分析
created_atISO 日期時間"2024-01-15T10:30:00-05:00"追蹤商品新增時間(新品偵測)
updated_atISO 日期時間"2025-03-01T08:00:00-05:00"偵測目錄近期變動
published_atISO 日期時間"2024-01-16T00:00:00-05:00"了解商品何時在前台上線
tags字串陣列["organic", "women", "straight-leg"]標籤/關鍵字分析,可用於 SEO、分類與趨勢觀察
variants物件陣列(見下方變體欄位)每個變體的價格、SKU、可購買狀態
images物件陣列(見下方圖片欄位)商品圖片網址,可用於目錄與視覺分析
options物件陣列[{"name": "Size", "values": ["S","M","L"]}]理解商品規格(尺寸、顏色、材質)

變體層級欄位(嵌在每個商品下)

欄位資料類型範例用途
id整數987654321變體唯一識別碼
title字串"32 / Blue"變體顯示名稱
sku字串"HD-BLU-32"供庫存系統對應的 SKU
price字串"185.00"價格監控(注意這是字串,做運算時要轉成 float)
compare_at_price字串或 null"200.00"原價,折扣追蹤必備
available布林值true庫存可售狀態(公開端點唯一能看到的庫存指標)
weight浮點數1.2運輸/物流分析
option1, option2, option3字串"32", "Blue", null各個選項值
created_at, updated_atISO 日期時間變體層級變更追蹤

圖片層級欄位

欄位資料類型範例用途
id整數111222333圖片唯一識別碼
src字串(URL)"https://cdn.shopify.com/..."圖片直接下載連結
alt字串或 null"Front view of jeans"圖片替代文字,可用於無障礙分析
position整數1圖片排序
width, height整數2048, 2048圖片尺寸

公開端點沒有的欄位

有一個很重要的坑:公開的 /products.json 回應中沒有 inventory_quantity 這個欄位在 2017 年 12 月就從公開 JSON 端點移除了,原因是安全性考量。你能拿到的唯一庫存指標,是每個變體上的布林欄位 availabletruefalse)。如果你要真正的庫存數量,就必須使用有驗證的 Admin API,並且具備商店擁有者權限。

在寫程式之前,先看過這張表,決定哪些欄位跟你的需求相關。如果你是做價格監控,就需要 variants[].pricevariants[].compare_at_pricevariants[].available。如果你是做名單開發,就聚焦在 vendorproduct_typetags。先過濾再輸出,CSV 會乾淨很多。

不只 products.json:Collections、Meta 與其他 Shopify 端點

很少有競品教學會提到這些端點,但如果你在做比較嚴謹的競爭情報分析,它們非常重要。

/collections.json — 商店所有分類

會回傳商店內所有集合(分類),包含標題、handle、描述和商品數量。我在 zoologistperfumes.com、allbirds.com 與 gymshark.com 都測過,全部都能正常回傳 JSON。

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

想了解競品是怎麼整理商品目錄的?就看這個端點。

/collections/{handle}/products.json — 依分類取得商品

這個端點會回傳某個特定集合底下的商品,JSON 結構和 /products.json 一樣,但只限於單一分類。這對分類層級的抓取很重要——例如你只想監控競品的「Sale」或「New Arrivals」分類。

/meta.json — 商店層級中繼資料

會回傳商店名稱、描述、幣別、國家,還有最重要的 published_products_count。有了這個數字,你就能先算出需要幾頁分頁:ceil(published_products_count / 250)。不用再傻傻地一路加頁數,直到碰到空回應才停。

你該用哪個端點?

你的需求端點需要驗證嗎?
全部商品(公開)/products.json
特定分類中的商品/collections/{handle}/products.json
商店中繼資料 + 商品數量/meta.json
所有集合(分類)/collections.json
訂單/銷售資料(僅限自己商店)Admin API /orders.json是(API key)
庫存數量(僅限自己商店)Admin API /inventory_levels.json

大家最常問的問題是:「我能抓到競品賣了幾件嗎?」答案很直接:不能。至少不能從公開端點拿到。銷售資料和庫存數量都需要驗證後的 Admin API,也就是你必須擁有商店存取權。公開端點只提供商品目錄資料。

shopify-data-access-methods.webp

用 Python 抓 Shopify:一步一步設定教學

  • 難度: 初學者
  • 所需時間: 約 15 分鐘(設定 + 第一次抓取)
  • 你需要準備: Python 3.11 以上、pip、終端機,以及一個要抓取的 Shopify 商店網址

步驟 1:安裝 Python 與必要函式庫

先確認你已安裝 Python 3.11 以上版本(pandas 3.0.x 需要)。接著安裝我們需要的兩個套件:

1pip install requests pandas

如果要匯出 Excel,還需要:

1pip install openpyxl

在程式最上方加入以下匯入:

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

執行時如果沒有 import 錯誤,就代表安裝正常。如果 pandas 出現版本錯誤,請升級到 Python 3.12。

步驟 2:從 /products.json 取得商品資料

下面是一個基本函式,輸入商店網址後,會向端點發送請求並回傳解析後的 JSON:

1def fetch_products_page(store_url, page=1, limit=250):
2    """從 Shopify 商店抓取單一頁商品資料。"""
3    url = f"{store_url.rstrip('/')}/products.json"
4    params = {"limit": limit, "page": page}
5    headers = {
6        "User-Agent": "Mozilla/5.0 (compatible; ProductResearch/1.0)"
7    }
8    response = requests.get(url, params=params, headers=headers, timeout=30)
9    response.raise_for_status()
10    return response.json().get("products", [])

幾個重點:

  • limit=250 是 Shopify 每頁允許的上限。預設只有 30,所以明確設定可以把請求數量最多減少 8 倍。
  • User-Agent 標頭:一定要設定一個像真實瀏覽器的字串。沒有 User-Agent 的請求,更容易觸發 Shopify 的防機器人機制。
  • timeout=30:避免單一請求卡住太久。

用一個已知商店測試看看:

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

你應該會看到像這樣的輸出:Fetched 250 products,以及第一個商品標題。

步驟 3:處理分頁,把所有商品都抓下來

單次請求最多只能拿到 250 個商品。很多商店都超過這個數量(Allbirds 就有 1,420+ 個)。你需要持續迴圈翻頁,直到拿到空回應。

1def scrape_all_products(store_url, delay=1.0):
2    """抓取 Shopify 商店的所有商品,並處理分頁。"""
3    all_products = []
4    page = 1
5    while True:
6        print(f"Fetching page {page}...")
7        products = fetch_products_page(store_url, page=page, limit=250)
8        if not products:
9            print(f"No more products. Total: {len(all_products)}")
10            break
11        all_products.extend(products)
12        print(f"  Got {len(products)} products (total so far: {len(all_products)})")
13        page += 1
14        # 禮貌一點:每次請求之間稍微等一下
15        time.sleep(delay + random.uniform(0, 0.5))
16    return all_products

products 回傳空陣列時,就代表已經抓到最後一頁。

time.sleep() 再加上隨機抖動,可以把請求頻率維持在 Shopify 大致可接受的非正式速率限制內(約每秒 2 次)。

小技巧:如果你先抓 /meta.json,就能知道總商品數,直接算出需要幾頁:pages = ceil(product_count / 250)。這樣就不會在最後多送一次空請求。

步驟 4:解析並挑選你需要的欄位

現在你已經拿到一個由字典組成的 Python list,接著只要擷取你關心的欄位即可。以下範例示範如何抓出最常見的價格監控欄位:

1def extract_product_data(products):
2    """從商品中擷取關鍵欄位,並將變體展平。"""
3    rows = []
4    for product in products:
5        for variant in product.get("variants", []):
6            rows.append({
7                "product_id": product["id"],
8                "title": product["title"],
9                "handle": product["handle"],
10                "vendor": product.get("vendor", ""),
11                "product_type": product.get("product_type", ""),
12                "tags": ", ".join(product.get("tags", [])),
13                "created_at": product.get("created_at", ""),
14                "variant_id": variant["id"],
15                "variant_title": variant.get("title", ""),
16                "sku": variant.get("sku", ""),
17                "price": variant.get("price", ""),
18                "compare_at_price": variant.get("compare_at_price", ""),
19                "available": variant.get("available", ""),
20                "image_url": product["images"][0]["src"] if product.get("images") else ""
21            })
22    return rows

這會建立一筆變體對應一列的資料格式——對價格比較最實用,因為像「Classic Blue Jeans」這類商品可能有 12 個變體(6 種尺寸 × 2 種顏色),每個變體都有自己的價格與可售狀態。

用 pandas 將抓取到的 Shopify 資料匯出成 CSV 與 Excel

其他 Shopify 抓取教學通常只會把原始 JSON 存成檔案就結束了。對開發者來說還行,對需要在週五前交出試算表的電商分析師來說,根本不夠。

問題在於:Shopify 的 JSON 是巢狀結構。一個商品可能包含十幾個變體,而每個變體都有自己的價格、SKU 和可售性。要把它攤平成列與欄,就需要借助 pandas。

把巢狀 JSON 攤平成乾淨表格

根據你的需求,可以有兩種做法:

方案 A:一個變體一列(最適合價格監控與庫存追蹤)

1# 使用步驟 4 的 extract_product_data 函式
2products = scrape_all_products("https://allbirds.com")
3rows = extract_product_data(products)
4df = pd.DataFrame(rows)
5print(f"DataFrame shape: {df.shape}")
6print(df.head())

這會得到一張平面表格,每一列都是唯一的商品+變體組合。一個有 500 個商品、平均每個商品 4 個變體的商店,最後大約會產生 2,000 列的 DataFrame。

方案 B:一個商品一列的摘要表(最適合做目錄總覽)

1def summarize_products(products):
2    """每個商品一列,顯示各變體的最低/最高價格。"""
3    rows = []
4    for product in products:
5        prices = [float(v["price"]) for v in product.get("variants", []) if v.get("price")]
6        rows.append({
7            "product_id": product["id"],
8            "title": product["title"],
9            "vendor": product.get("vendor", ""),
10            "product_type": product.get("product_type", ""),
11            "variant_count": len(product.get("variants", [])),
12            "min_price": min(prices) if prices else None,
13            "max_price": max(prices) if prices else None,
14            "any_available": any(v.get("available", False) for v in product.get("variants", [])),
15            "tags": ", ".join(product.get("tags", []))
16        })
17    return rows

匯出成 CSV、Excel 與 Google Sheets

1# 匯出 CSV(使用 utf-8-sig,讓 Excel 能正確處理特殊字元)
2df.to_csv("shopify_products.csv", index=False, encoding="utf-8-sig")
3# 匯出 Excel(需要 openpyxl)
4df.to_excel("shopify_products.xlsx", index=False, engine="openpyxl")
5print("已匯出為 shopify_products.csv 和 shopify_products.xlsx")

如果要匯出到 Google Sheets,可以用 gspread 搭配 service account。不過老實說,對大多數情境而言,直接輸出 CSV 再上傳到 Google Drive 會更快也更簡單。

可上線使用的 Python 抓取:速率限制、重試與防封鎖

前面的基礎腳本抓小型商店沒問題。但如果你要抓 5,000+ 個商品的商店,或是連續抓多個商店,問題就會開始冒出來。

了解 Shopify 的速率限制與封鎖機制

Shopify 的公開 JSON 端點沒有像 Admin API 那樣明確文件化的速率限制(Admin API 採用的是漏桶模型),但實際測試會發現:

  • 安全速度:每個商店約每秒 2 個請求
  • 軟性上限:每分鐘約 40 個請求後,開始可能出現節流
  • HTTP 429:"Too Many Requests",標準的速率限制回應
  • HTTP 430:Shopify 特有代碼,表示安全層級封鎖,不只是限流
  • HTTP 403 或 CAPTCHA 重新導向:有些商店會再加 Cloudflare 防護

來自共享雲端基礎設施(例如 AWS Lambda、Google Cloud Run)的請求,特別容易被攔下,因為那些 IP 段常被拿來做濫用。

穩定抓取 Shopify 的技巧

下面這個表可以看出從「筆電上跑得動」到「可在正式環境運行」的演進:

等級技巧可靠度
基本requests.get() + ?page=大型目錄容易失敗,也可能被封鎖
進階requests.Session() + ?limit=250 + time.sleep(1) + 429 重試適用於多數商店
高階非同步 httpx + 輪換 User-Agent + 指數退避可用於正式環境,能擴展到 1 萬+ 商品

進階方案(多數使用者都適合):

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

Retry 設定會在遇到 429 時自動做指數退避。backoff_factor=1 代表重試間隔會依序是 0.5 秒 → 1 秒 → 2 秒 → 4 秒 → 8 秒。使用 requests.Session() 重複連線,也能透過連線池降低同一網域多次請求的額外成本。

User-Agent 輪換:如果你要抓多個商店,建議輪流使用 3–5 組真實的瀏覽器 User-Agent 字串。這不是為了欺騙,而是避免每次請求都送出一模一樣的標頭,看起來太像機器人。

完整可執行的 Python 腳本:抓取 Shopify 並輸出 CSV

以下是完整、可直接複製貼上的腳本,把前面的內容全部整合在一起。實際程式碼大約 75 行(加上註解),我已經拿 Allbirds(1,420 個商品)、ColourPop(2,000+ 商品)以及 Zoologist Perfumes(小型目錄)測試過。

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

python scrape_shopify.py 執行即可。以 Allbirds 為例,整個過程大約需要 45 秒,最後會產生一份約 5,000+ 列的 CSV(每個變體一列)。終端機輸出大概會像這樣:

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

不想寫 Python?用 Thunderbit 2 步驟抓 Shopify(免寫程式替代方案)

不是每個人都想安裝 Python、處理 import 錯誤,或維護抓取腳本。對於明天早上就要競品價格資料的業務來說,Python 可能太重了。

這也是我們打造 的原因——一款以 Chrome 擴充功能形式運作的 AI 網頁爬蟲。免寫程式、免 API 金鑰,也不用設定環境。

Thunderbit 如何抓 Shopify 商店

Thunderbit 內建專為 Shopify 商品頁設計的 Shopify 爬蟲範本。你只要安裝 ,打開 Shopify 商店,然後按下「Scrape」。這個範本會自動擷取商品名稱、描述、價格、變體細節、圖片與供應商資訊。

如果某些商店的版型不完全符合範本(例如自訂主題、特殊排版),Thunderbit 的 AI Suggest Fields 功能會直接讀取頁面,並自動產生欄位名稱。你還可以自己調整,例如重新命名欄位、增加欄位,或寫入像「只抓 compare_at_price 有值的商品」這類指令。

以下幾個功能,和前面 Python 程式能做的事情幾乎一樣:

  • 子頁面抓取:自動前往每個商品詳細頁,補充完整描述、評論或變體細節——等同於我們在 Python 程式裡逐頁抓取,但完全不用寫程式。
  • 自動分頁:可自動處理點擊式分頁和無限捲動,不需要額外設定。
  • 排程抓取:可設定週期性任務(例如「每週一上午 9 點」)持續監控價格,不需要 cron job 或伺服器。
  • 免費匯出:所有方案都可免費匯出到 CSV、Excel、Google Sheets、Airtable 或 Notion。

Python 腳本 vs. Thunderbit:誠實比較

比較項目Python 腳本Thunderbit(免寫程式)
設定時間15–60 分鐘(環境 + 程式碼)約 2 分鐘(安裝 Chrome 擴充功能)
需要寫程式嗎需要(Python)不需要
客製化能力幾乎無上限AI 建議欄位 + 自訂提示詞
分頁處理需自行撰寫自動處理
匯出格式需自行程式化(CSV/Excel)CSV、Excel、Google Sheets、Airtable、Notion(免費)
排程執行需 cron job + 主機內建排程器
速率限制處理需自行實作重試/退避自動處理
最適合誰開發者、大規模資料流程商務使用者、快速擷取、持續監控

當你需要完整控制權,或要把資料整合進更大的資料管線時,用 Python。當你想快速拿到資料、不想維護程式時,用 Thunderbit。如果你想更深入了解 ,我們也另外寫了一篇專文。

python-vs-thunderbit-comparison.webp

抓 Shopify 商店的技巧與最佳實踐

不管你用什麼工具,下面這些原則都適用:

  • 一定要用 ?limit=250,把請求數降到最低。預設每頁 30 筆,代表同樣資料要多做 8 倍請求。
  • 尊重商店伺服器:每次請求間停 1–2 秒。瘋狂連打伺服器不只是壞習慣,也更容易被封鎖。
  • 先檢查 robots.txt:Shopify 預設的 robots.txt 不會擋 /products.json,但有些商店會加自訂規則,所以大量抓取前還是要確認一下。
  • 先把原始 JSON 存到本地,再進行處理。如果之後解析邏輯變了,就不用重新抓一次。先做個 json.dump(all_products, open("raw_data.json", "w")) 再展平,能省很多麻煩。
  • product.id 去重:分頁邊界偶爾可能出現重複商品,df.drop_duplicates(subset=["product_id", "variant_id"]) 可以快速清理。
  • 做數學運算前先把 price 轉成 float。Shopify 回傳的是字串(例如 "185.00"),不是數字。
  • 持續監控端點變動:雖然 /products.json 多年來都很穩定,但 Shopify 理論上仍可能調整限制。如果你的爬蟲突然 404,先手動檢查商店頁面。

如果你想了解更穩健的爬蟲設計,可以參考我們關於 的指南。

抓 Shopify 時的法律與倫理考量

篇幅不長,但很重要。

/products.json 端點提供的是公開可見的商品資料——也就是任何訪客在商店前台都能看到的內容。Shopify 的服務條款雖然有提到不能用「自動化方式」存取「服務」,但這裡指的是平台本身(像是後台管理、結帳流程),不是公開前台資料。到 2026 年 4 月為止,尚未有針對 Shopify 公開資料抓取的專門訴訟。

已有一些重要判例支持公開資料抓取:hiQ v. LinkedIn 確立了抓取公開可存取資料不違反 CFAA,而 Meta v. Bright Data(2024)則指出,TOS 限制主要適用於使用者登入後的情況。

最佳做法:

  • 只抓取公開可見的商品資料
  • 不要抓個人或客戶資料
  • 遵守 robots.txt 與速率限制
  • 如果處理到任何個人資料,請遵守 GDPR/CCPA(商品目錄資料不屬於個資)
  • 使用清楚的 User-Agent 字串表明身分
  • 抓取自己商店的資料時,透過 Admin API 永遠是沒問題的

若你想更深入了解,可閱讀我們關於 的文章。

結論與重點整理

Shopify 的公開 /products.json 端點,讓電商資料擷取變成一件相對簡單的事。整體流程就是:在網址後加上 /products.json → 用 Python 取得資料 → 用 ?limit=250&page= 分頁 → 用 pandas 展平 → 匯出成 CSV 或 Excel。

這篇指南比其他教學更完整的地方包括:

  • 完整欄位參考:在寫任何程式碼前,就能清楚知道有哪些資料可用(涵蓋商品、變體與圖片的 40+ 欄位)
  • 額外端點/collections.json/meta.json 提供分類層級情報與商店中繼資料,這是其他教學少提到的
  • 可上線使用的技巧:session 重用、指數退避、User-Agent 標頭與 ?limit=250,用來應對真實環境中的速率限制
  • 正確的 CSV/Excel 匯出方式:使用 pandas 把變體層級資料攤平,而不是只丟一包原始 JSON
  • 免寫程式替代方案:對於偏好速度勝過程式彈性的使用者,推薦

如果你只是要一次性或定期抓 Shopify 資料,又不想寫程式,可以試試 ——內建的 Shopify 爬蟲範本可處理從分頁到匯出的所有流程。如果你要為多個商店建立客製化資料管線,或要大規模抓取,這篇文章中的 Python 腳本會給你完整控制權。

也歡迎到我們的 看影片教學,或延伸閱讀我們關於 的相關指南。

試用 Thunderbit 進行 Shopify 抓取

常見問題

可以用 products.json 抓任何 Shopify 商店嗎?

大多數 Shopify 商店預設都會開放這個端點——根據測試,大約 71% 會回傳有效 JSON。有些啟用自訂設定或額外安全防護(例如 Cloudflare、無頭架構)的商店,可能會回 404 或直接擋掉請求。快速檢查方式:直接在瀏覽器打開 {store-url}/products.json。如果看得到 JSON,就代表可以抓。

抓 Shopify 商店是否合法?

公開商品資料(價格、標題、圖片、描述)通常是可取得的,而且像 hiQ v. LinkedIn 這類法律先例也支持抓取公開資訊。不過你還是應該查看該商店的服務條款以及當地法律。不要抓個人或客戶資料,並遵守速率限制。

一個 Shopify 商店最多可以抓多少商品?

總數沒有硬性上限。使用 ?limit=250&page= 分頁,就能把整個目錄都抓下來。若是超大型商店(25,000+ 商品),建議搭配 session 重用與延遲,避免觸發速率限制。/meta.json 端點可以事先告訴你確切商品數,方便你預估會有幾頁。

products.json 跟 Shopify Admin API 有什麼差別?

/products.json 是公開端點——不需要驗證、只提供唯讀商品資料、任何人都能存取。Admin API 則需要商店擁有者的存取權杖,會提供訂單、庫存數量、客戶資料,以及寫入權限。如果你需要銷售資料或實際庫存數量,就必須使用 Admin API(也就是你必須是商店擁有者,或得到對方授權)。

不用 Python 也能抓 Shopify 嗎?

當然可以。像 這類工具,就能透過 Chrome 擴充功能免寫程式抓取 Shopify 商店。它會自動處理分頁,並直接匯出到 CSV、Excel、Google Sheets、Airtable 或 Notion。若你是偏好其他語言的開發者,同樣的 /products.json 端點也能搭配 JavaScript、Ruby、Go——任何能送出 HTTP 請求並解析 JSON 的語言都可以。

延伸閱讀

Ke
Ke
CTO @ Thunderbit. Ke is the person everyone pings when data gets messy. He's spent his career turning tedious, repetitive work into quiet little automations that just run. If you've ever wished a spreadsheet could fill itself in, Ke has probably already built the thing that does it.
目錄

試試 Thunderbit

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

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