用 Python 抓取 Target.com:2026 年真正可行的 3 種方法

最後更新於 April 28, 2026
用 Python 抓取 Target.com:2026 年真正可行的 3 種方法

Target.com 是那種看起來很簡單、實際上卻不太好抓的網站。您如果曾經寫過一個用 Requests 和 BeautifulSoup 的 Python 小腳本,丟到 Target 的商品頁,結果價格欄位回傳 None,其實一點也不孤單。

我測試過多數大型零售網站的抓取方式,可以很肯定地說:Target 一直都屬於最棘手的那一類。它每月有 2.08 億到 2.8 億次造訪,商品資料像是價格、評分、庫存、評論都很有價值,但 Target 結合了 React 的前端渲染與 Akamai 的機器人偵測,讓天真的抓取方法幾乎一開始就失敗。不過,確實有三種 Python 方法真正可行。我會逐一說明,解釋為什麼第一種嘗試通常會失敗,並示範一個不用寫程式的替代方案,讓您在 Python 不值得折騰時也有退路。

為什麼您第一次用 Python 抓 Target.com 會回傳 None

先別急著想解法,先看問題出在哪。這是多數初學者會寫的程式:

import requests
from bs4 import BeautifulSoup

url = "https://www.target.com/p/some-product/-/A-12345678"
response = requests.get(url, headers={"User-Agent": "Mozilla/5.0"})
soup = BeautifulSoup(response.text, "html.parser")

price = soup.select_one('[data-test="current-price"]')
print(price)  # None

輸出是什麼?None。每次都一樣。

這不是您程式的錯。requests.get() 從 Target 拿回來的 HTML 幾乎只是個骨架——一個 React 外殼,意思是「嘿,載入這段 JavaScript 來渲染真正的頁面吧」。商品價格、評分、評論與可用性,都是在初始頁面載入之後才由 JavaScript 注入。因為 Python 的 Requests 不會執行 JavaScript,所以那些元素根本不會出現在回應裡。

論壇上到處都是撞上這堵牆的開發者。某篇 ScrapeOps 分析說得很直接:「元素會顯示為 None,是因為它是由 Javascript 渲染,而 requests 無法抓取由 Javascript 渲染的 HTML。」Crawlbase 教學也證實:「當您向 Target URL 發送 HTTP 請求時,HTML 回應中沒有什麼有用的資料。」

而且就算您解決了 JavaScript 問題,還有第二層:Target 的 Akamai 機器人偵測會先對您的 TLS 握手做指紋辨識,在傳送任何一個 HTML 位元組之前,就先把 Python 的 requests 庫標記出來。這點我等一下會再講。

為什麼 Target.com 這麼難用 Python 抓

Target 不只是「一個用了 JavaScript 的網站」。它其實是一套分層防禦系統——了解每一層,才能選對抓取方法。

JavaScript 渲染的商品資料

Target.com 是用 React 建置的。當您在真正的瀏覽器裡打開商品頁或搜尋頁時,流程是這樣:

  1. 伺服器送出最小化的 HTML 骨架
  2. JavaScript bundle 載入並執行
  3. 前端呼叫 Target 內部的 Redsky API
  4. 商品資料(價格、評分、圖片、可用性)渲染進 DOM

如果您跳過第 2 到第 4 步——也就是 requests.get() 做的事——您拿到的就只是一個空頁面。GroupBWT 有做過基準測試,靜態 HTTP 請求在 Target 上大約只能抓到 30% 的可用資料。其餘 70% 需要 JavaScript 執行或 API 存取。

搜尋結果頁更糟。初始 HTML 只會出現少數幾個商品;其餘商品得等您往下捲動才會載入。

Target 的反機器人防禦:不只是泛泛地說「用代理」

多數抓取教學對反機器人措施都只會輕描淡寫地說「用代理就好」。但 Target 的防線其實更值得細講。

TLS 指紋辨識(最關鍵的一層)。 在 HTTPS 握手期間,您的客戶端會送出一個「Client Hello」封包,裡面會暴露您的 TLS 版本、cipher suites、擴充套件與橢圓曲線。這些資訊會被雜湊成一個 JA3 指紋。Python 的 requests 會產生一個 固定且已知的雜湊值——8d9f7747675e24454cd9b7ed35c58707——反機器人資料庫會立刻標記它。Chrome 會送出 16 個經過仔細排序、包含 GREASE 值的 cipher suites;Python 則會以非瀏覽器順序送出 60 多個。封鎖會在任何 HTTP 內容交換之前就發生。

IP 信譽評分。 Akamai 會把 IP 分到不同信任等級。資料中心 IP 在 Scrapfly 的說法裡會得到「顯著的負面信任分數,因為它們很可能被機器人使用」。住宅 IP 則會得到正面分數。以 Target 來說,資料中心 IP 範圍幾乎會立刻被標記。

JavaScript 指紋辨識。 Akamai 會注入 JavaScript,收集您的 JS 引擎規格、硬體能力、作業系統資料、字型、外掛程式與行為資料(打字速度、滑鼠移動、點擊時間)。這會生成 _abck cookie——一種有狀態的指紋權杖。沒有有效的 _abck,請求就會被封鎖。

速率限制。 Target 大約每個 IP 每分鐘觸發 30 到 60 次請求時就會出現 429 錯誤。有些使用者回報會收到看起來像 200 OK 的回應,但實際內容是「Pardon Our Interruption」封鎖頁,這讓自動化偵測更棘手。

整體來看,ScrapeOps 給 Target 的難度評分是 7/10。而 Akamai 繞過部分則被評為 9/10

用 Python 抓 Target.com 的 3 種方法(並排比較)

外面沒有一篇文章會把這三種可行方法完整放在一起比較。下面我直接整理給您:

比較項目Requests + BS4Selenium / PlaywrightRedsky API
支援 JS 渲染❌ 否✅ 是✅ 是(JSON)
每筆速度⚡ 約 0.5–1 秒🐢 約 5–10 秒⚡ 約 0.5–1 秒
反機器人風險⚠️ 高(TLS 指紋)⚠️ 中⚠️ 中(驗證金鑰可能變動)
設定複雜度中高(逆向工程)
資料完整度約 30%(僅靜態 HTML)約 95%(整頁)約 90%(結構化 JSON)
最適合用途靜態中繼資料、__TGT_DATA__完整商品頁、評論大量商品資料擷取

接下來我們一種一種來做。

方法 1:用 Python Requests 和 BeautifulSoup 抓 Target.com

這個方法抓不到搜尋頁上由 JavaScript 渲染的價格。不過它速度快、很輕量,而且如果您知道該看哪裡,其實能抓到比您想像更多的資料。

關鍵在於:Target 會在 <script> 標籤裡嵌入一部分商品資料,裡面有個 __TGT_DATA__ 變數,含有 __PRELOADED_QUERIES__。這個 JSON 區塊會包含商品名稱、描述、特色,有時候甚至會在單一商品頁中包含價格。您也可以從搜尋結果 HTML 中擷取商品標題與 URL。

步驟 1:設定 Python 環境

建立專案資料夾並安裝相依套件:

mkdir target-scraper && cd target-scraper
python -m venv venv
source venv/bin/activate  # Windows 上:venv\Scripts\activate
pip install requests beautifulsoup4 curl_cffi

這裡建議用 curl_cffi 取代標準 requests。它會偽裝瀏覽器的 TLS 指紋,這是避免被 Target 擋下來最重要的一步。基準測試顯示 curl_cffi 的反機器人繞過成功率有 92%,而標準 requests 只有 12%——大約提升 15 倍。

步驟 2:抓取 Target 搜尋結果

Target 的搜尋 URL 格式很直接:https://www.target.com/s?searchTerm={keyword}

from curl_cffi import requests as cureq
from bs4 import BeautifulSoup
import time, random

headers = {
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36",
    "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
    "Accept-Language": "en-US,en;q=0.9",
}

url = "https://www.target.com/s?searchTerm=bluetooth+headphones"
resp = cureq.get(url, headers=headers, impersonate="chrome124")
soup = BeautifulSoup(resp.text, "html.parser")

# 商品卡片使用這個 data-test 屬性
cards = soup.find_all("div", {"data-test": "@web/site-top-of-funnel/ProductCardWrapper"})
for card in cards:
    link_tag = card.find("a")
    title = link_tag.get_text(strip=True) if link_tag else "N/A"
    href = "https://www.target.com" + link_tag["href"] if link_tag and link_tag.get("href") else "N/A"
    print(f"{title} — {href}")

您會拿到商品名稱和 URL。價格呢?多半不會出現在這份 HTML 裡。這很正常。

步驟 3:從商品頁擷取嵌入的 JSON 資料

單一商品頁會把更豐富的資料嵌在 __TGT_DATA__ script tag 裡:

import re, json

product_url = "https://www.target.com/p/some-product/-/A-12345678"
resp = cureq.get(product_url, headers=headers, impersonate="chrome124")
soup = BeautifulSoup(resp.text, "html.parser")

# 找出 __TGT_DATA__ script
scripts = soup.find_all("script")
for script in scripts:
    if script.string and "__TGT_DATA__" in script.string:
        # 從 script 內容中擷取 JSON
        match = re.search(r'__TGT_DATA__\s*=\s*({.*?});?\s*$', script.string, re.DOTALL)
        if match:
            tgt_data = json.loads(match.group(1))
            # 導向 JSON 結構找商品細節
            queries = tgt_data.get("__PRELOADED_QUERIES__", {})
            # 商品資料被巢狀包在裡面——實際結構會因頁面而異
            print(json.dumps(queries, indent=2)[:500])  # 預覽結構

__TGT_DATA__ 裡的 JSON 結構包含商品名稱、描述、特色,以及常常會有價格資料。實際巢狀層級會變動,所以您需要先看輸出,再決定怎麼走。

步驟 4:處理分頁

Target 的搜尋分頁使用 Nao 參數。第 1 頁是 Nao=0,第 2 頁是 Nao=24,第 3 頁是 Nao=48,以此類推(每次加 24):

for page in range(0, 120, 24):  # 前 5 頁
    paginated_url = f"https://www.target.com/s?searchTerm=bluetooth+headphones&Nao={page}"
    resp = cureq.get(paginated_url, headers=headers, impersonate="chrome124")
    # 解析與擷取...
    time.sleep(random.uniform(2, 5))  # 禮貌一點

步驟 5:儲存抓到的資料

import csv

with open("target_products.csv", "w", newline="", encoding="utf-8") as f:
    writer = csv.DictWriter(f, fieldnames=["title", "url", "price", "description"])
    writer.writeheader()
    for product in products:
        writer.writerow(product)

您能拿到什麼: 商品標題、URL、描述與嵌入式中繼資料。您不容易穩定拿到什麼: 搜尋結果頁的動態價格和評分。這些通常要靠方法 2 或 3。

方法 2:用 Selenium 或 Playwright 抓 Target.com

無頭瀏覽器會渲染 JavaScript、載入動態內容,並模擬真實使用者行為。這就是能抓到價格、評分與評論的方法。

關於 Selenium 和 Playwright 的選擇:Playwright 的採用率已經超過 Selenium——2026 年是 45.1% 對 22.1%——而且基準測試顯示它還 快 2.5 倍(20 頁 11 秒對 28 秒)。我這裡會示範 Selenium,因為它社群更大、教學更多;但如果您是從零開始,Playwright 其實是更好的選擇。

步驟 1:安裝 Selenium 與 ChromeDriver

pip install selenium webdriver-manager

webdriver-manager 會自動處理 ChromeDriver 版本,從此不用再煩惱「ChromeDriver 版本不相符」:

from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.chrome.options import Options
from webdriver_manager.chrome import ChromeDriverManager

options = Options()
options.add_argument("--headless=new")
options.add_argument("--window-size=1920,1080")
options.add_argument("--disable-blink-features=AutomationControlled")
options.add_argument("--user-agent=Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36")

driver = webdriver.Chrome(service=Service(ChromeDriverManager().install()), options=options)

步驟 2:載入 Target 頁面並等待內容出現

from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC

driver.get("https://www.target.com/s?searchTerm=bluetooth+headphones")

# 等待商品卡片渲染完成(顯式等待 > time.sleep)
WebDriverWait(driver, 15).until(
    EC.presence_of_element_located((By.CSS_SELECTOR, '[data-test="product-title"]'))
)

顯式等待很重要。time.sleep(10) 對載入快的頁面是在浪費時間,對載入慢的頁面又不夠久——兩頭都吃虧。WebDriverWait 會每 500 毫秒輪詢一次,直到元素出現或逾時。

步驟 3:捲動頁面以載入全部商品

Target 會隨著您捲動才懶載入商品。不捲動的話,您可能只會看到 4 到 5 個商品,而不是整頁:

import time

last_height = driver.execute_script("return document.body.scrollHeight")
for _ in range(10):
    driver.execute_script("window.scrollBy(0, 300);")
    time.sleep(1.5)
    new_height = driver.execute_script("return document.body.scrollHeight")
    if new_height == last_height:
        break
    last_height = new_height

ScrapeOps 的測試證實,10 次捲動、每次延遲 1.5 秒,可抓到 8 個以上商品;不捲動則只有 4 到 5 個。每次捲動建議 200 到 300px,比較像真人行為。

步驟 4:從渲染後的頁面擷取商品資料

products = []
cards = driver.find_elements(By.CSS_SELECTOR, '[data-test="@web/site-top-of-funnel/ProductCardWrapper"]')

for card in cards:
    try:
        title = card.find_element(By.CSS_SELECTOR, '[data-test="product-title"]').text
    except:
        title = "N/A"
    try:
        price = card.find_element(By.CSS_SELECTOR, '[data-test="current-price"]').text
    except:
        price = "N/A"
    try:
        link = card.find_element(By.CSS_SELECTOR, 'a[href*="/p/"]').get_attribute("href")
    except:
        link = "N/A"

    products.append({"title": title, "price": price, "link": link})

for p in products:
    print(f'{p["title"]} — {p["price"]}')

Target 可用的關鍵 data-test 選擇器(2026 年驗證):

資料欄位選擇器
商品卡片data-test="@web/site-top-of-funnel/ProductCardWrapper"
商品標題data-test="product-title"
目前價格data-test="current-price"
評分值data-test="rating-value"
評分數量data-test="rating-count"

步驟 5:抓取商品評論(加分項)

前往單一商品頁,捲動到評論區,然後擷取評論資料:

from bs4 import BeautifulSoup

driver.get("https://www.target.com/p/some-product/-/A-12345678")
# 往下捲動以載入評論
for _ in range(5):
    driver.execute_script("window.scrollBy(0, 500);")
    time.sleep(2)

soup = BeautifulSoup(driver.page_source, "html.parser")
reviews = soup.find_all("div", {"data-test": "review-card--text"})
for review in reviews:
    print(review.get_text(strip=True)[:100])

評論透過 Bazaarvoice 整合載入,支援分頁(最多 51 頁)、依最近排序,以及只看圖片的篩選。 ScrapeOps 基準測試顯示,Selenium 每筆大約要 5.1 秒。

做完記得關閉瀏覽器:

driver.quit()

方法 3:用 Redsky API 抓 Target.com

Target 前端會從 redsky.target.com 這個內部 API 抓取所有資料。您可以直接用 Python 呼叫它——不用解析 HTML、不用瀏覽器、不用 JavaScript 渲染。回傳的是乾淨的 JSON,裡面有 40 多個資料欄位,涵蓋價格、評分、評論、圖片、可用性、履約、規格與變體。若是大量商品資料,這是最快也最可靠的方法,差距非常明顯。

步驟 1:用 Chrome DevTools 找出 Redsky API

多數教學會直接跳過這步,但其實您自己也能找到 API:

  1. 用 Chrome 打開任一 Target 商品頁
  2. 開啟 DevTools(F12)→ Network 分頁
  3. Fetch/XHR 篩選
  4. 重新整理頁面
  5. 找到對 redsky.target.comredsky.a]target.com 的請求
  6. 點進去看 Request URLHeaders

您會看到類似這樣的網址:

https://redsky.target.com/redsky_aggregations/v1/web/pdp_fulfillment_v1?key=9f36aeafbe60771e321a7cc95a78140772ab3e96&tcin=12345678&store_id=2148&zip=55401

關鍵參數:

  • key — API 金鑰(固定,不會輪替——不同端點會用不同的 key)
  • tcin — Target.com Item Number(8 位數商品 ID)
  • store_id — Target 門市代碼
  • zip — 用於履約資料的郵遞區號

把 API key 從 request headers 裡擷取出來。它其實已經作為 query parameter 寫在網址中了。

步驟 2:直接用 Python 呼叫 Redsky API

from curl_cffi import requests as cureq
import json

API_KEY = "9f36aeafbe60771e321a7cc95a78140772ab3e96"  # 從 DevTools 擷取
TCIN = "12345678"

url = f"https://redsky.target.com/redsky_aggregations/v1/web/pdp_fulfillment_v1?key={API_KEY}&tcin={TCIN}&store_id=2148&zip=55401"

headers = {
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36",
    "Accept": "application/json",
    "Origin": "https://www.target.com",
    "Referer": "https://www.target.com/",
    "Sec-Fetch-Site": "same-site",
    "Sec-Fetch-Mode": "cors",
    "Sec-Fetch-Dest": "empty",
}

resp = cureq.get(url, headers=headers, impersonate="chrome124")
data = resp.json()

# 從 JSON 回應擷取商品資料
product = data.get("data", {}).get("product", {})
title = product.get("item", {}).get("product_description", {}).get("title", "N/A")
price = product.get("price", {}).get("formatted_current_price", "N/A")
rating = product.get("ratings_and_reviews", {}).get("statistics", {}).get("rating", {}).get("average", "N/A")

print(f"{title} — {price} — 評分:{rating}")

不用解析 HTML。回應結構清楚、乾淨又快速。

步驟 3:透過 API 抓取商品搜尋結果

product_summary_with_fulfillment_v1 端點一次可以接受多個 TCIN:

tcins = ["12345678", "23456789", "34567890"]
tcin_str = ",".join(tcins)

search_url = f"https://redsky.target.com/redsky_aggregations/v1/web/product_summary_with_fulfillment_v1?key={API_KEY}&tcins={tcin_str}&store_id=2148&zip=55401"

resp = cureq.get(search_url, headers=headers, impersonate="chrome124")
results = resp.json()

for item in results.get("data", {}).get("product_summaries", []):
    title = item.get("title", "N/A")
    price = item.get("price", {}).get("formatted_current_price", "N/A")
    print(f"{title} — {price}")

要取得 TCIN,可以從搜尋頁 HTML 中擷取(商品 URL 會顯示成 /A-XXXXXXXX),或者從內嵌的 __TGT_DATA__ JSON 裡拿。

步驟 4:用並行請求擴大規模

from concurrent.futures import ThreadPoolExecutor
import time, random

def fetch_product(tcin):
    url = f"https://redsky.target.com/redsky_aggregations/v1/web/pdp_fulfillment_v1?key={API_KEY}&tcin={tcin}&store_id=2148&zip=55401"
    time.sleep(random.uniform(2, 5))
    resp = cureq.get(url, headers=headers, impersonate="chrome124")
    return resp.json()

tcin_list = ["12345678", "23456789", "34567890", "45678901"]

with ThreadPoolExecutor(max_workers=3) as executor:
    results = list(executor.map(fetch_product, tcin_list))

並行數量要保守——3 到 5 個執行緒,外加 2 到 5 秒的隨機延遲。Target 的速率限制大約是每個 IP 每分鐘 30 到 60 次請求

關於 Redsky API 的重要注意事項

在您把這個做成正式生產管線之前,先留意幾件事:

  • API key 雖然固定,但只對特定端點有效。 不同 Redsky 端點會使用不同的 key。它們不常輪替,但 Target 隨時可能改。
  • 這是未公開文件的內部 API。 Target 的工程團隊已經確認它是刻意公開可用,這降低了法律風險,但它並不是有 SLA 的官方公開 API。
  • 商品變體(顏色、尺寸)各自有獨立的 TCIN。 您需要逐一查詢每個變體。
  • 少了 Sec-Fetch-* headers 會立刻被擋。 這是常見陷阱——務必包含 Sec-Fetch-SiteSec-Fetch-ModeSec-Fetch-Dest

如何在大規模抓取 Target.com 時避免被封鎖

以下做法適用於正式規模,不論您用哪一種方法。

使用住宅代理輪換,不要用資料中心代理

Target 的 Akamai 會一眼認出資料中心 IP 範圍。要長期抓取,住宅代理幾乎是必需品。價格差異很大——Smartproxy/Decodo 起價每 GB 4.50 美元Bright Data 每 GB 5.04 美元,大量使用時可降到每 GB 3 到 4 美元。

每 50 到 100 次請求輪換一次 IP;如果您的代理池支援,也可以每次請求都換。

用 curl_cffi 偽裝 TLS 指紋

這是您能做的、影響最大的單一改動。直接替換 requests

from curl_cffi import requests as cureq

# 標準 requests —— 在受保護網站上的成功率約 12%
# resp = requests.get(url, headers=headers)

# curl_cffi —— 成功率約 92%
resp = cureq.get(url, headers=headers, impersonate="chrome124")

curl_cffi(GitHub 8,200+ 星)支援從 chrome99chrome146 的 Chrome 版本,也支援 Safari、Edge 與行動裝置變體。在同步模式下,它比 tls_client 快 20% 到 30%

設定合理的請求節奏與標頭

  • 隨機延遲: 每次請求間隔 2 到 7 秒(不要固定間隔——隨機性很重要)
  • User-Agent 輪換: 維護 5 到 10 組真實瀏覽器 User-Agent 字串並輪替使用
  • Session 預熱: 先拜訪 target.com 首頁,再進入商品頁,以建立 cookie
  • 標頭一致性: 您的 Sec-Ch-Ua 必須和您聲稱的瀏覽器版本一致。Sec-Ch-Ua-Platform 也必須和您聲稱的作業系統一致。不一致很容易被看穿。
  • Session 持續性: 在同一個 session 裡保留 cookies。Scraperly 建議搭配輪換住宅代理,維持 48 小時的 session 穩定度。

不想寫程式?用 Thunderbit 抓 Target.com(無程式碼替代方案)

說真的,Target.com 是程式化抓取零售網站中比較難的一種。JavaScript 渲染、Akamai 的 TLS 指紋辨識、資料中心代理偵測、ChromeDriver 版本問題——每一項都會卡您。如果您是在學 Python,這很適合作為練習;但如果您是為了實際工作要拿到 Target 商品資料,投入產出常常不划算。

如果您想直接拿到資料、不想碰工程細節,Thunderbit 會自動處理最難的部分。

Thunderbit 如何處理 Target.com 的難題

Thunderbit 的人工智慧網頁爬蟲是在瀏覽器中執行,這代表它會自然渲染 JavaScript——不用裝 Selenium,不用設定無頭瀏覽器,也不用管 ChromeDriver 版本。瀏覽器本身就是爬蟲。

流程如下:

  1. 安裝 Thunderbit Chrome 擴充功能 並前往 Target 的商品頁或搜尋頁
  2. 點擊「AI Suggest Fields」——Thunderbit 會讀取頁面並提出欄位名稱建議(商品標題、價格、評分、圖片 URL 等)
  3. 點擊「Scrape」——資料會在幾秒內直接從渲染後的頁面擷取出來

不用設定代理。不用偽裝 TLS 指紋。不會再看到 None

抓取 Target 商品列表與詳細頁

多頁工作流程最有意思。您可以先抓 Target 搜尋結果頁拿到商品清單,再用 子頁面抓取 自動逐一拜訪每個商品 URL,並把詳細頁資料豐富到表格中——像是描述、完整評論、規格等,不必自己寫分頁程式,也不用管理瀏覽器 session。

可以直接匯出到 Excel、Google Sheets、Airtable 或 Notion。沒有 csv.writer 的樣板程式,也沒有檔案編碼問題。

自動化重複性的 Target.com 抓取

如果您要持續監控價格或追蹤庫存,Thunderbit 的 排程爬蟲 可以讓您用自然語言描述排程(例如「每週一上午 9 點」)。不用 cron job、不用架伺服器、不用在 VPS 上維持 Python 腳本一直跑。這對追蹤競品價格的電商團隊特別有用——81% 的美國零售商現在都在使用自動化價格抓取,而價格情報的平均投資報酬率高達 27:1

用 Python 抓 Target.com 時,什麼情況該用哪一種方法

給您一個快速決策框架:

你的情況建議方法
在學 Python、小型專案方法 1:Requests + BS4(靜態資料與 __TGT_DATA__
需要完整商品頁,包含價格與評論方法 2:Selenium / Playwright
大量擷取商品資料方法 3:Redsky API
需要快速拿資料,不想寫程式Thunderbit(無程式碼)
需要持續監控價格Thunderbit 排程爬蟲或 Redsky API + cron
一次性的研究專案,團隊非技術背景Thunderbit——老實說是最快的路徑

如果您是在打造正式的資料管線,方法 3(Redsky API)在速度和穩定性上表現最好。如果您只是做一次性研究,或團隊沒有 Python 能力,Thunderbit 可以幫您省下好幾個小時。如果您是在學網頁抓取,方法 1 → 方法 2 → 方法 3 是很自然的學習路線,而且每一步都能學到真正有用的東西。

抓取 Target.com 的法律與倫理考量

這部分值得簡短說明。Target 的 robots.txt 大約有 120 多條 Disallow 路徑,但明顯沒有封鎖 /p/(商品)或 /c/(分類)——商品頁與分類頁都明確允許爬取。購物車、帳號與結帳頁則是受限制的。

Target 的服務條款確實禁止自動化存取。不過,Redsky API 被刻意設計成對外可見(Target 工程團隊已確認),這會降低以 API 為基礎進行資料收集的法律風險。

您應該知道的主要法律判例:

  • hiQ v. LinkedIn(第九巡迴法院,2022):抓取公開可得資料不違反 CFAA
  • Meta v. Bright Data(2024):Meta 敗訴——法院認定抓取公開資料不構成 CFAA 違反

如果是大規模商業抓取,請諮詢法律顧問。若是市場研究、價格比較或個人專案,且使用的是公開資料,基本上站得住腳。務必尊重速率限制,不要讓 Target 的伺服器負載過高。

結論與重點整理

Target.com 的難度名符其實。天真的 Requests + BeautifulSoup 做法會失敗,是因為 Target 透過 JavaScript 渲染商品資料,而且 Akamai 甚至會在您拿到回應前就先對 TLS 握手做指紋辨識。不過,選對方法後,抓取其實並不複雜。

三種方法的可靠度排名:

  1. Redsky API —— 速度最快、最適合大量資料、回傳乾淨 JSON。需要先用 DevTools 逆向找出 API 端點。
  2. Selenium / Playwright —— 能處理 JavaScript 渲染,可以拿到頁面上的所有內容。速度較慢,但資料完整。
  3. Requests + BeautifulSoup —— 只適用於靜態 HTML 與嵌入的 __TGT_DATA__ JSON。速度快,但不完整。

最大的技術重點:

  • curl_cffi 取代標準 requests,反機器人繞過能力可提升 15 倍
  • 住宅代理是必要條件——資料中心 IP 會立刻被標記
  • 每次請求都加入 Sec-Fetch-* headers——少了會立刻被擋
  • session 預熱(先拜訪首頁)會明顯提高成功率

如果對您的用途來說,Python 抓取太麻煩,Thunderbit 的 Chrome 擴充功能會自動處理 JavaScript 渲染、反機器人措施與資料匯出。試試看免費方案,看看能不能在幾分鐘內而不是幾小時內拿到您要的資料。

想看更多抓取教學和資料擷取技巧,可以參考 Thunderbit 部落格 或我們的 YouTube 頻道

常見問題

我可以只用 Python Requests 和 BeautifulSoup 抓 Target.com 嗎?

部分可以。您可以從商品頁的 __TGT_DATA__ script tag 擷取商品標題、URL 和一些嵌入式 JSON 資料。但搜尋結果頁上的價格、評分、評論與可用性都是 JavaScript 渲染的,靜態 HTTP 請求看不到。要拿完整資料,請用 Selenium/Playwright 或 Redsky API。

為什麼我的 Target.com 爬蟲價格欄位會回傳 None?

Target 會在初始頁面載入後再用 JavaScript 載入價格資料。當您使用 requests.get() 時,拿到的是尚未渲染完成的 HTML 骨架——也就是 JavaScript 執行、把商品資料注入 DOM 之前的版本。價格元素在回應裡根本不存在。請改用能渲染 JavaScript 的無頭瀏覽器(Selenium 或 Playwright)、直接呼叫 Redsky API 取得 JSON,或者使用像 Thunderbit 這類會從渲染後瀏覽器頁面擷取資料的工具。

抓取 Target.com 合法嗎?

依照目前美國的判例,抓取公開可得資料通常是被允許的(hiQ v. LinkedIn、Meta v. Bright Data)。Target 的 robots.txt 也允許商品頁與分類頁被爬取。不過,Target 的服務條款禁止自動化存取,所以仍有灰色地帶。若是用公開資料做市場研究或價格比較,法律上通常較站得住腳;若是大規模商業運作,請諮詢律師。

Target 的 Redsky API 是什麼?我要怎麼存取?

Redsky 是 Target 的內部 API,負責前端商品資料。它不是那種您註冊帳號、拿 API 文件與 API key 的公開 API;它是 React 應用在渲染商品頁時所呼叫的後端。您可以打開 Chrome DevTools,切到 Network 分頁並用 XHR/Fetch 篩選,找出對 redsky.target.com 的請求來發現端點。API key 會以 query parameter 的形式嵌在 request URL 中。Target 工程團隊已確認這個 API 是刻意對外可見的。

我要怎麼避免在抓 Target.com 時被封鎖?

最有影響的一個改動,就是用 curl_cffi 取代標準 Python requests,偽裝瀏覽器的 TLS 指紋——單這一步就能把成功率從 12% 提升到 92%。除此之外:使用住宅代理(不要用資料中心)、輪換 User-Agent 字串、每次請求之間加入 2 到 7 秒隨機延遲、加入所有 Sec-Fetch-* headers,並先拜訪首頁做 session 預熱。或者,直接用像 Thunderbit 這樣會自動處理反機器人措施的工具,完全不用設定。

延伸閱讀

Ke
Ke
Thunderbit 技術長|資深資料科學家與機器學習專家 Ke Shen 在機器學習與資料科學領域擁有近十年經驗,畢業於哥倫比亞大學,曾任 Walmart Labs 資深資料科學家。他精通 Python、R、Java 與統計學,且具備深受同儕認可的深厚專業,分享如何將複雜的 AI 演算法從理論落實到可投入生產的架構的實戰見解。
目錄

只要提問,就能抓取網頁

用白話告訴它你要什麼,或者更好,什麼都不用說。

立即體驗 Thunderbit free
使用 AI 擷取資料
輕鬆將資料轉移到 Google Sheets、Airtable 或 Notion
Chrome Store Rating
PRODUCT HUNT#1 Product of the Week