用 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
3> This paragraph contains content that cannot be parsed and has been skipped.
4price = soup.select_one('[data-test="current-price"]')
5print(price)  # None

输出是什么?None。每次都是。

这不是你代码的 bug。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 包加载并执行
  3. 前端调用 Target 内部的 Redsky API
  4. 商品数据(价格、评分、图片、库存)渲染进 DOM

如果你跳过第 2–4 步——而这正是 requests.get() 会做的——拿到的就是一个空页面。:静态 HTTP 请求只能抓到 Target 上大约 的可用数据。剩下的 70% 需要执行 JavaScript,或者直接访问 API。

搜索结果页更糟。初始 HTML 里只会出现少量商品,其余内容要等你滚动页面时才加载出来。

Target 的反爬防御:别再只会说“用代理”

大多数抓取教程谈到反爬时都很笼统,只会说“换代理就行了”。但 Target 的防护值得更具体地拆解。

TLS 指纹识别(最关键的一层)。 在 HTTPS 握手阶段,你的客户端会发送一个“Client Hello”包,里面包含 TLS 版本、密码套件、扩展、椭圆曲线等信息。这些内容会被哈希成一个 JA3 指纹。Python 的 requests 库会生成一个 —— 8d9f7747675e24454cd9b7ed35c58707 —— 反爬数据库会立刻把它识别出来。Chrome 会发送 16 个经过精心排序、带 GREASE 值的密码套件;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 种方法(横向对比)

网上很少有文章能把这三种可行方案放在一起比较。这里我直接给你摆出来,并老实评估:

This paragraph contains content that cannot be parsed and has been skipped.

下面我们逐个搭建。

方法 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
4> This paragraph contains content that cannot be parsed and has been skipped.
5url = "https://www.target.com/s?searchTerm=bluetooth+headphones"
6resp = cureq.get(url, headers=headers, impersonate="chrome124")
7soup = BeautifulSoup(resp.text, "html.parser")
8> This paragraph contains content that cannot be parsed and has been skipped.
9你会拿到商品名称和 URL。价格呢?大概率不会出现在这个 HTML 里。这很正常。
10### 第 3 步:从商品页提取内嵌 JSON 数据
11单个商品页会把更丰富的数据嵌到 `__TGT_DATA__` 脚本标签中:
12```python
13import re, json
14product_url = "https://www.target.com/p/some-product/-/A-12345678"
15resp = cureq.get(product_url, headers=headers, impersonate="chrome124")
16soup = BeautifulSoup(resp.text, "html.parser")
17> This paragraph contains content that cannot be parsed and has been skipped.
18`__TGT_DATA__` 里的 JSON 结构包含商品名称、描述、特性,并且经常包含价格数据。具体嵌套层级会变,所以你需要先检查输出,再按实际结构去取值。
19### 第 4 步:处理分页
20Target 的搜索分页使用 `Nao` 参数。第 1 页是 `Nao=0`,第 2 页是 `Nao=24`,第 3 页是 `Nao=48`,以此类推(每页加 24):
21```python
22for page in range(0, 120, 24):  # 前 5 页
23    paginated_url = f"https://www.target.com/s?searchTerm=bluetooth+headphones&Nao={page}"
24    resp = cureq.get(paginated_url, headers=headers, impersonate="chrome124")
25    # 解析并提取……
26    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 会每 500ms 轮询一次,直到元素出现或者超时。

第 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–300 像素最接近真人行为。

第 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> This paragraph contains content that cannot be parsed and has been skipped.
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)
7> This paragraph contains content that cannot be parsed and has been skipped.
8评论由 Bazaarvoice 集成加载,支持分页(最多 51 页)、按最近排序,以及仅看图片的筛选。 [ScrapeOps 的基准测试](https://scrapeops.io/) 显示,Selenium 单个条目大约要 5.1 秒。
9别忘了处理完后关闭浏览器:
10```python
11driver.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 密钥(静态,不轮换;不同端点使用不同密钥)
  • tcin —— Target.com 商品编号(8 位商品 ID)
  • store_id —— Target 门店编号
  • zip —— 用于履约数据的邮政编码

从请求头里把 API 密钥提取出来。它作为查询参数直接嵌在 URL 中。

第 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"
6> This paragraph contains content that cannot be parsed and has been skipped.
7resp = cureq.get(url, headers=headers, impersonate="chrome124")
8data = resp.json()
9# 从 JSON 响应中提取商品详情
10product = data.get("data", {}).get("product", {})
11title = product.get("item", {}).get("product_description", {}).get("title", "N/A")
12price = product.get("price", {}).get("formatted_current_price", "N/A")
13rating = product.get("ratings_and_reviews", {}).get("statistics", {}).get("rating", {}).get("average", "N/A")
14print(f"{title}{price} — Rating: {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 的速率限制大约是

关于 Redsky API 的重要注意事项

在你把它做成生产级流水线之前,有几件事要注意:

  • API 密钥是静态的,但和端点绑定。 不同的 Redsky 端点使用不同密钥。它们不会频繁轮换,但 Target 可能随时更改。
  • 这是一个未公开文档的内部 API。 Target 工程团队已经 ,这降低了法律风险,但它并不是带 SLA 的官方公共 API。
  • 商品变体(颜色、尺寸)各自有独立 TCIN。 你需要逐个变体查询。
  • 缺少 Sec-Fetch-* 请求头会立刻被拦截。 这是常见坑——一定要带上 Sec-Fetch-SiteSec-Fetch-ModeSec-Fetch-Dest

如何在大规模抓取 Target.com 时避免被封

这些做法适用于生产级规模,不管你用哪种方法。

使用住宅代理轮换,不要用机房代理

Target 的 Akamai 实现会一眼识别机房 IP 段。要持续抓取,住宅代理是必须的。价格差异很大——,大流量时可降到 $3–4/GB。

每 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 条真实浏览器 UA 并轮换使用
  • 会话预热: 先访问 target.com 首页,再请求商品页,以建立 Cookie
  • 请求头一致性: 你的 Sec-Ch-Ua 必须和你声明的浏览器版本一致,Sec-Ch-Ua-Platform 也必须和操作系统一致。不一致非常容易暴露
  • 会话持久化: 同一个会话中尽量保持 Cookie 连续。 使用可持续 48 小时的会话稳定性,并配合轮换住宅代理

不写代码也能抓:用 Thunderbit 抓 Target.com(无代码方案)

说实话,Target.com 确实是最难用程序抓取的零售网站之一。JavaScript 渲染、Akamai 的 TLS 指纹、机房代理检测、ChromeDriver 版本问题——环节很多。如果你正在学 Python,这当然是很好的练习;但如果你是为了实际工作拿到 Target 商品数据,这种投入产出常常并不划算。

如果你只是想拿到数据,而不是做工程项目, 会自动帮你处理这些难点。

Thunderbit 如何应对 Target.com 的难点

Thunderbit 的 AI 网页爬虫运行在你的浏览器里,所以它天然就能渲染 JavaScript——不需要配置 Selenium,不需要无头浏览器设置,也不需要管理 ChromeDriver 版本。浏览器本身就是爬虫。

工作流程很简单:

  1. 安装 ,然后打开 Target 的商品页或搜索页
  2. 点击“AI 建议字段”——Thunderbit 会读取页面并推荐列名(商品标题、价格、评分、图片 URL 等)
  3. 点击“抓取”——数据会在几秒内直接从渲染后的页面提取出来

不需要配置代理,不需要伪装 TLS 指纹,也不会再出现 None

抓取 Target 商品列表和详情页

多页抓取流程才是真正有意思的部分。你可以先抓 Target 搜索结果页,拿到商品列表,然后使用子页面抓取自动访问每个商品 URL,把详情页的数据(描述、完整评论、规格参数)补充进表格里,而不用自己写分页代码,也不用管理浏览器会话。

你可以直接导出到 Excel、Google Sheets、Airtable 或 Notion。没有 csv.writer 样板代码,也没有文件编码问题。

自动化定期抓取 Target.com

如果你要持续监控价格或库存,Thunderbit 的定时爬虫可以用自然语言描述计划(例如“每周一上午 9 点”)。不需要 cron 任务,不需要服务器配置,也不用在 VPS 上一直挂着 Python 脚本。这对跟踪的电商团队尤其有用——现在都在使用自动化价格抓取,而价格情报的平均 ROI 约为

用 Python 抓 Target.com 时该选哪种方法

给你一个快速决策框架:

This paragraph contains content that cannot be parsed and has been skipped.

如果你要搭建生产级数据管道,方法 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-* 请求头——缺了就会立刻被拦
  • 会话预热(先访问首页)能显著提高成功率

如果对你的场景来说,Python 的折腾成本不值得,可以自动处理 JavaScript 渲染、反爬措施和数据导出。试试,看看它能不能在几分钟内而不是几小时内帮你拿到想要的数据。

想看更多抓取指南和数据提取技巧,可以浏览 或我们的

常见问题

只用 Python Requests 和 BeautifulSoup 能抓 Target.com 吗?

可以,但只能抓一部分。你能从商品页的 __TGT_DATA__ 脚本标签里提取商品标题、URL 和部分嵌入的 JSON 数据。不过,搜索结果页上的价格、评分、评论和库存信息都是由 JavaScript 渲染的,静态 HTTP 请求拿不到。要完整数据,请用 Selenium/Playwright 或 Redsky API。

为什么我的 Target.com 爬虫价格总是返回 None?

因为 Target 会在初始页面加载后通过 JavaScript 再加载价格数据。当你使用 requests.get() 时,你拿到的是 JavaScript 执行之前的 HTML 外壳——商品数据还没有注入 DOM。价格元素在响应里根本不存在。你可以使用能渲染 JavaScript 的无头浏览器(Selenium 或 Playwright),直接调用 Redsky API 获取 JSON,或者使用像 这样从渲染后浏览器页面抓取的工具。

抓 Target.com 合法吗?

根据当前美国判例,抓取公开可访问的数据通常是允许的(hiQ 诉 LinkedIn、Meta 诉 Bright Data)。Target 的 robots.txt 也允许抓取商品页和分类页。不过,Target 的服务条款禁止自动化访问,所以法律上存在灰色地带。用于市场研究和价格对比的公开数据抓取,通常法律风险相对可控;但如果是大规模商业运营,建议先咨询律师。

Target 的 Redsky API 是什么?怎么访问?

Redsky 是 Target 的内部 API,负责前端商品数据。它不是那种你注册后能拿到文档和 API Key 的公共 API,而是 React 应用在渲染商品页时调用的后端接口。你可以通过打开 Chrome DevTools,在 Network 标签页按 XHR/Fetch 过滤,查找发往 redsky.target.com 的请求来发现它。API Key 会作为查询参数直接嵌在请求 URL 里。Target 工程团队已经确认该 API 是有意面向公众开放的。

怎么避免抓 Target.com 时被封?

最有效的单点改动,是用 curl_cffi 替代标准 Python requests 来伪装浏览器 TLS 指纹——这一个改动就能把成功率从 。除此之外:使用住宅代理(不要用机房代理)、轮换 User-Agent 字符串、请求之间加入随机 2–7 秒延迟、带上所有 Sec-Fetch-* 请求头,并通过先访问首页来预热会话。或者直接使用像 这样的工具,自动处理反爬措施,不需要任何配置。

了解更多

试试 Thunderbit

只需 2 次点击即可抓取线索及其他数据。由 AI 驱动。

Get Thunderbit It’s free
使用 AI 提取数据
轻松将数据传输到 Google Sheets、Airtable 或 Notion
PRODUCT HUNT#1 Product of the Week