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

最後更新:April 28, 2026

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

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

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

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

1import requests
2from bs4 import BeautifulSoup
3url = "https://www.target.com/p/some-product/-/A-12345678"
4response = requests.get(url, headers={"User-Agent": "Mozilla/5.0"})
5soup = BeautifulSoup(response.text, "html.parser")
6price = soup.select_one('[data-test="current-price"]')
7print(price)  # None

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

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

論壇上到處都是撞上這堵牆的開發者。某篇 說得很直接:「元素會顯示為 None,是因為它是由 Javascript 渲染,而 requests 無法抓取由 Javascript 渲染的 HTML。」也證實:「當您向 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() 做的事——您拿到的就只是一個空頁面。,靜態 HTTP 請求在 Target 上大約只能抓到 的可用資料。其餘 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 在 裡會得到「顯著的負面信任分數,因為它們很可能被機器人使用」。住宅 IP 則會得到正面分數。以 Target 來說,資料中心 IP 範圍幾乎會立刻被標記。

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

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

整體來看,。而 Akamai 繞過部分則被評為

用 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 環境

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

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

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

步驟 2:抓取 Target 搜尋結果

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

1from curl_cffi import requests as cureq
2from bs4 import BeautifulSoup
3import time, random
4headers = {
5    "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",
6    "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
7    "Accept-Language": "en-US,en;q=0.9",
8}
9url = "https://www.target.com/s?searchTerm=bluetooth+headphones"
10resp = cureq.get(url, headers=headers, impersonate="chrome124")
11soup = BeautifulSoup(resp.text, "html.parser")
12# 商品卡片使用這個 data-test 屬性
13cards = soup.find_all("div", {"data-test": "@web/site-top-of-funnel/ProductCardWrapper"})
14for card in cards:
15    link_tag = card.find("a")
16    title = link_tag.get_text(strip=True) if link_tag else "N/A"
17    href = "https://www.target.com" + link_tag["href"] if link_tag and link_tag.get("href") else "N/A"
18    print(f"\{title\} — \{href\}")

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

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

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

1import re, json
2product_url = "https://www.target.com/p/some-product/-/A-12345678"
3resp = cureq.get(product_url, headers=headers, impersonate="chrome124")
4soup = BeautifulSoup(resp.text, "html.parser")
5# 找出 __TGT_DATA__ script
6scripts = soup.find_all("script")
7for script in scripts:
8    if script.string and "__TGT_DATA__" in script.string:
9        # 從 script 內容中擷取 JSON
10        match = re.search(r'__TGT_DATA__\s*=\s*({.*?});?\s*$', script.string, re.DOTALL)
11        if match:
12            tgt_data = json.loads(match.group(1))
13            # 導向 JSON 結構找商品細節
14            queries = tgt_data.get("__PRELOADED_QUERIES__", {})
15            # 商品資料被巢狀包在裡面——實際結構會因頁面而異
16            print(json.dumps(queries, indent=2)[:500])  # 預覽結構

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

步驟 4:處理分頁

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

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

步驟 5:儲存抓到的資料

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

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

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

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

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

步驟 1:安裝 Selenium 與 ChromeDriver

1pip install selenium webdriver-manager

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

1from selenium import webdriver
2from selenium.webdriver.chrome.service import Service
3from selenium.webdriver.chrome.options import Options
4from webdriver_manager.chrome import ChromeDriverManager
5options = Options()
6options.add_argument("--headless=new")
7options.add_argument("--window-size=1920,1080")
8options.add_argument("--disable-blink-features=AutomationControlled")
9options.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")
10driver = webdriver.Chrome(service=Service(ChromeDriverManager().install()), options=options)

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

1from selenium.webdriver.common.by import By
2from selenium.webdriver.support.ui import WebDriverWait
3from selenium.webdriver.support import expected_conditions as EC
4driver.get("https://www.target.com/s?searchTerm=bluetooth+headphones")
5# 等待商品卡片渲染完成(顯式等待 > time.sleep)
6WebDriverWait(driver, 15).until(
7    EC.presence_of_element_located((By.CSS_SELECTOR, '[data-test="product-title"]'))
8)

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

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

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

1import time
2last_height = driver.execute_script("return document.body.scrollHeight")
3for _ in range(10):
4    driver.execute_script("window.scrollBy(0, 300);")
5    time.sleep(1.5)
6    new_height = driver.execute_script("return document.body.scrollHeight")
7    if new_height == last_height:
8        break
9    last_height = new_height

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

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

1products = []
2cards = driver.find_elements(By.CSS_SELECTOR, '[data-test="@web/site-top-of-funnel/ProductCardWrapper"]')
3for card in cards:
4    try:
5        title = card.find_element(By.CSS_SELECTOR, '[data-test="product-title"]').text
6    except:
7        title = "N/A"
8    try:
9        price = card.find_element(By.CSS_SELECTOR, '[data-test="current-price"]').text
10    except:
11        price = "N/A"
12    try:
13        link = card.find_element(By.CSS_SELECTOR, 'a[href*="/p/"]').get_attribute("href")
14    except:
15        link = "N/A"
16    products.append({"title": title, "price": price, "link": link})
17for p in products:
18    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:抓取商品評論(加分項)

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

1from bs4 import BeautifulSoup
2driver.get("https://www.target.com/p/some-product/-/A-12345678")
3# 往下捲動以載入評論
4for _ in range(5):
5    driver.execute_script("window.scrollBy(0, 500);")
6    time.sleep(2)
7soup = BeautifulSoup(driver.page_source, "html.parser")
8reviews = soup.find_all("div", {"data-test": "review-card--text"})
9for review in reviews:
10    print(review.get_text(strip=True)[:100])

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

做完記得關閉瀏覽器:

1driver.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

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

1https://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

1from curl_cffi import requests as cureq
2import json
3API_KEY = "9f36aeafbe60771e321a7cc95a78140772ab3e96"  # 從 DevTools 擷取
4TCIN = "12345678"
5url = f"https://redsky.target.com/redsky_aggregations/v1/web/pdp_fulfillment_v1?key=\{API_KEY\}&tcin=\{TCIN\}&store_id=2148&zip=55401"
6headers = {
7    "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",
8    "Accept": "application/json",
9    "Origin": "https://www.target.com",
10    "Referer": "https://www.target.com/",
11    "Sec-Fetch-Site": "same-site",
12    "Sec-Fetch-Mode": "cors",
13    "Sec-Fetch-Dest": "empty",
14}
15resp = cureq.get(url, headers=headers, impersonate="chrome124")
16data = resp.json()
17# 從 JSON 回應擷取商品資料
18product = data.get("data", {}).get("product", {})
19title = product.get("item", {}).get("product_description", {}).get("title", "N/A")
20price = product.get("price", {}).get("formatted_current_price", "N/A")
21rating = product.get("ratings_and_reviews", {}).get("statistics", {}).get("rating", {}).get("average", "N/A")
22print(f"\{title\} — \{price\} — 評分:\{rating\}")

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

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

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

1tcins = ["12345678", "23456789", "34567890"]
2tcin_str = ",".join(tcins)
3search_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"
4resp = cureq.get(search_url, headers=headers, impersonate="chrome124")
5results = resp.json()
6for item in results.get("data", {}).get("product_summaries", []):
7    title = item.get("title", "N/A")
8    price = item.get("price", {}).get("formatted_current_price", "N/A")
9    print(f"\{title\} — \{price\}")

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

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

1from concurrent.futures import ThreadPoolExecutor
2import time, random
3def fetch_product(tcin):
4    url = f"https://redsky.target.com/redsky_aggregations/v1/web/pdp_fulfillment_v1?key=\{API_KEY\}&tcin=\{tcin\}&store_id=2148&zip=55401"
5    time.sleep(random.uniform(2, 5))
6    resp = cureq.get(url, headers=headers, impersonate="chrome124")
7    return resp.json()
8tcin_list = ["12345678", "23456789", "34567890", "45678901"]
9with ThreadPoolExecutor(max_workers=3) as executor:
10    results = list(executor.map(fetch_product, tcin_list))

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

關於 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 範圍。要長期抓取,住宅代理幾乎是必需品。價格差異很大——,大量使用時可降到每 GB 3 到 4 美元。

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

用 curl_cffi 偽裝 TLS 指紋

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

1from curl_cffi import requests as cureq
2# 標準 requests —— 在受保護網站上的成功率約 12%
3# resp = requests.get(url, headers=headers)
4# curl_cffi —— 成功率約 92%
5resp = cureq.get(url, headers=headers, impersonate="chrome124")

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

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

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

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

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

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

Thunderbit 如何處理 Target.com 的難題

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

流程如下:

  1. 安裝 並前往 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 腳本一直跑。這對追蹤的電商團隊特別有用——現在都在使用自動化價格抓取,而價格情報的平均投資報酬率高達

用 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 為基礎進行資料收集的法律風險。

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

  • (第九巡迴法院,2022):抓取公開可得資料不違反 CFAA
  • (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,反機器人繞過能力可提升
  • 住宅代理是必要條件——資料中心 IP 會立刻被標記
  • 每次請求都加入 Sec-Fetch-* headers——少了會立刻被擋
  • session 預熱(先拜訪首頁)會明顯提高成功率

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

想看更多抓取教學和資料擷取技巧,可以參考 或我們的

常見問題

我可以只用 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,或者使用像 這類會從渲染後瀏覽器頁面擷取資料的工具。

抓取 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 指紋——單這一步就能把成功率從 。除此之外:使用住宅代理(不要用資料中心)、輪換 User-Agent 字串、每次請求之間加入 2 到 7 秒隨機延遲、加入所有 Sec-Fetch-* headers,並先拜訪首頁做 session 預熱。或者,直接用像 這樣會自動處理反機器人措施的工具,完全不用設定。

延伸閱讀

試試 Thunderbit

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

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