Bright Data 评测与替代方案:迁移您的爬虫
Scraping and Proxy Management Expert
TL;DR:
- Bright Data 通过一个端点路由两个不同的产品。 Web Unlocker 和 SERP API 都 POST 到
https://api.brightdata.com/request;只有请求体中的zone决定哪个响应。因此,迁移首先要通过去复用你的区域,而不是交换主机名。 - 在简单的迁移中有三件事会出错, 而且它们都不会引发有用的错误:身份验证头的名称发生变化,响应以 JSON 信封的方式到达,而不是原始标记,并且这两个表面位于不同的 API 版本上。
- 浏览器自动化是简单的一环。 两个产品都支持 CDP,因此 Playwright 和 Puppeteer 代码在更改连接 URL 后仍然有效。凭据从 URL 的用户信息移动到查询参数。
- 无论如何都有一个截止日期迫使这个问题。 Bright Data 自己的 FAQ 指出代理端口
22225和33335的证书将在 2026 年 9 月 25 日过期,呼叫者必须转移到端口44445。在此之前,每个集成都将在进行中开放。 - 开始免费: Scrapeless 仪表板 发放一个能够在这里描述的每个表面上工作的密钥。
Bright Data 是什么
Bright Data 将网络数据收集作为一套在一个代理网络上运行的独立品牌产品出售。在移动抓取器代码时,有三个产品是重要的:
- Web Unlocker API — 你提供一个 URL,它处理代理旋转、指纹和挑战,并返回页面。
- SERP API — 针对搜索引擎的相同请求管道,你传递一个完全构建的搜索 URL。
- 浏览器 API — 你通过 Playwright、Puppeteer 或 Selenium 驱动的托管 Chrome,使用 Chrome DevTools 协议。
重要的结构事实,也是塑造每次迁移的事实是:前两个是相同的 HTTP 端点。 根据 Bright Data 的 Web Unlocker 文档 和 SERP API 文档,这两个产品都接受发送到 https://api.brightdata.com/request 的 POST 请求,携带 zone、url 和 format。zone 值是路由调用的关键。
在 Bright Data 上时这很方便,但当你离开时就显得尴尬,因为你的代码库可能有一个请求助手,其行为依赖于一个配置字符串。
关键特性
在这三个产品中,请求表面小而一致:
- 身份验证是作为
Authorization: Bearer <key>发送的单一账户 API 密钥。 - 路由由
zone决定,在仪表板中配置,而不是在请求中。 format: "raw"直接返回目标的响应体。- 地理定位、会话固定和移动用户代理通过代理用户名内的后缀表示,例如
-country-<code>和-session-<id>。 - 浏览器 API 连接在
wss://<username>:<password>@brd.superproxy.io:9222,依据 Bright Data 的浏览器 API 配置参考。
产品和定价
Bright Data 按产品和区域定价,因此单个账户通常具有多个区域,带有不同的费率和限制。这种模型是迁移很少是单行更改的原因:区域同时作为计费和配置的边界,因此迁移时涉及成本分配以及路由。
Scrapeless 按请求使用一个密钥定价,而表面是由你呼叫的端点选择的,而不是由仪表板对象选择的。当前两个方面的数字在各自的定价页面上;本指南故意映射机制,而不是引用波动的费率。
性能和适配性
Bright Data 的代理网络很大,而它在困难目标上的解锁成功率是大多数团队首先采用它的原因。本指南中的任何内容都没有论证该产品不起作用。
推动团队移动的通常是结构性而非技术性:每个区域的配置不稳定,计费很难归因于具体工作,以及保持多个区域一致的操作开销。这些条件下,“迁移代码”成为一个真正的问题。
Scrapeless 选择
Scrapeless 将相同的工作分散在由 URL 而不是由配置选择的表面上:
- 通用抓取 API —
POST https://api.scrapeless.com/api/v2/unlocker/request用于未阻塞页面的获取。 - 抓取 API —
POST https://api.scrapeless.com/api/v1/scraper/request,带有actor名称目标表面,内联回应解析字段。 - 抓取浏览器 — 一个 CDP 端点在
wss://browser.scrapeless.com/api/v2/browser,密钥作为token查询参数传递。
一个关键覆盖所有三者。没有区域对象,这消除了仪表板的往返,但也意味着解复用必须在您的代码中进行,在端口期间。
Bright Data 仍然占优势的地方
在 Bright Data 上,有三件事情确实比在移植后更容易做到:
- 当许多作业共享一个调用站点时,区域模型确实很方便,您希望在不部署的情况下更改行为。
- Selenium 在浏览器 API 上受到支持。无干扰抓取浏览器仅支持 CDP,因此基于 Selenium 的套件需要重写为 Playwright 或 Puppeteer,而不是重新指向。
- 代理用户名修饰符如
-country-和-session-表达地理和会话固定,而无需触及请求体,这使得一些代码库依赖很重。
模型让您付出代价的地方
- 一个端点,两个产品意味着静态分析无法告诉您给定调用实际做了什么,而无需解析区域。
- 配置位于代码库外部,因此区域更改对代码审查和
git blame是不可见的。 - 端口和证书波动由您承担。 Bright Data 的 常见问题解答 声明,在
22225和33335端口上的旧证书将在 2026 年 9 月 25 日 00:00 UTC 到期,仍在这些端口上的调用者必须在该日期之前完成迁移到44445端口。
实施:迁移代码
这是其他迁移的写作跳过的部分。下面的每个小节都是一个真实的差异,产生错误的结果而不是明确的错误。
端点和参数映射
| 关注点 | Bright Data | Scrapeless |
|---|---|---|
| 未阻塞页面提取 | POST https://api.brightdata.com/request · {"zone","url","format":"raw"} |
POST https://api.scrapeless.com/api/v2/unlocker/request · {"actor":"unlocker.webunlocker","input":{"url","js_render"}} |
| 搜索结果 | 相同的端点,SERP 区域 · url 是一个预构建的搜索 URL |
POST https://api.scrapeless.com/api/v1/scraper/request · {"actor":"scraper.google.search","input":{"q","gl","hl"}} · 返回内联解析结果 |
| 浏览器自动化 | wss://<user>:<pass>@brd.superproxy.io:9222 |
wss://browser.scrapeless.com/api/v2/browser?token=<key> |
| 认证 | Authorization: Bearer <key> |
x-api-token: <key> |
| 产品路由 | zone 在请求体中 |
端点加上 actor |
| 成功主体 | 目标的响应主体 | JSON 信封;内部标记 data |
破坏 1:认证头的名称更改
最常见的首次失败尝试是交换主机和密钥,但保持头部。Bright Data 使用 Authorization: Bearer;Scrapeless 使用 x-api-token。仅携带旧头部的请求未经过身份验证,失败的表现看起来像是凭证问题,而不是头部名称问题。
bash
# Bright Data — illustrative, from the vendor's published example
curl -H "Content-Type: application/json" \
-H "Authorization: Bearer ${BRIGHTDATA_API_KEY}" \
-d '{"zone":"YOUR_ZONE_NAME","url":"https://example.com","format":"raw"}' \
https://api.brightdata.com/request
bash
# Scrapeless — the same intent
curl -sS -X POST "https://api.scrapeless.com/api/v2/unlocker/request" \
-H "x-api-token: ${SCRAPELESS_API_KEY}" \
-H "Content-Type: application/json" \
-d '{"actor":"unlocker.webunlocker","input":{"url":"https://example.com","js_render":false}}'
破坏 2:响应是一个信封
使用 format: "raw",Bright Data 将目标的主体返还,因此调用者通常会 response.text 并解析它。Scrapeless 用 JSON 对象回应,并将标记放在 data 中。
更改的端口仅更改 URL 和头部会将 JSON 字符串解析为 HTML。选择器返回无内容,没有异常被触发,作业记录了空结果。修复只需一行,但前提是您知道要进行修复。
python
import os
import requests
KEY = os.environ["SCRAPELESS_API_KEY"]
def fetch(url: str, js_render: bool = False) -> str:
"""Return page HTML. The envelope is unwrapped here, once."""
response = requests.post(
"https://api.scrapeless.com/api/v2/unlocker/request",
headers={"x-api-token": KEY, "Content-Type": "application/json"},
json={"actor": "unlocker.webunlocker", "input": {"url": url, "js_render": js_render}},
timeout=90,
)
response.raise_for_status()
body = response.json()
# Bright Data with format:"raw" would have given you this directly as response.text
return body["data"]
html = fetch("https://example.com")
print(f"chars={len(html)} starts_with_doctype={html.lstrip().lower().startswith('<!doctype')}")
保持解包在一个辅助函数中。在调用站点散布 response.json()["data"] 是一部分代码库被迁移而另一部分安静地返回 JSON 的方式。
破坏 3:两个表面位于不同的 API 版本上
这一点让那些假设提供商只有一个 API 的人陷入困境。解锁器表面位于 /api/v2/;谷歌搜索参与者位于 /api/v1/。将搜索参与者发布到 v2 路径返回 HTTP 400 {"message":"unknown task type"} — 一条读起来像是格式错误主体的消息,让您检查 input 字段,而版本段才是真正的问题。
搜索调用本身是同步的。它在一次往返中以解析结果回应,因此没有任务标识符,也没有轮询循环。
python
import os
import requests
KEY = os.environ["SCRAPELESS_API_KEY"]
def search(query: str, gl: str = "us", hl: str = "en") -> dict:
"""Google SERP as structured JSON. Note the v1 path — the unlocker is v2."""
response = requests.post(
"https://api.scrapeless.com/api/v1/scraper/request",
headers={"x-api-token": KEY, "Content-Type": "application/json"},
json={"actor": "scraper.google.search", "input": {"q": query, "gl": gl, "hl": hl}},
timeout=120,
)
response.raise_for_status()
return response.json()
data = search("web scraping api")
print("sections:", sorted(data))
for row in data.get("organic_results", [])[:3]:
print(f" {row['position']}. {row['title'][:60]}")
print(f" {row['link']}")
这里更大的变化是返回的内容。Bright Data 的 SERP API 通过 format: "raw" 将搜索引擎的 HTML 交给您,您可以自己解析。Scrapeless 返回已经解析的页面 — 一次对 web scraping api 的实时调用返回了 organic_results, pagination, related_searches, search_information 和 metadata,其中每一行都有 position, title, link, snippet, source, favicon, redirect_link 和 snippet_highlighted_words。
迁移的两个后果。您的 SERP HTML 解析器变成冗余代码 — 删除它,而不是迁移它。而且您拥有的任何查询字符串组装也变得多余,因为查询和区域变成 input 作为 q, gl 和 hl,而不是烘焙在 URL 中。
破坏 4:浏览器凭据位置变动
两种产品都暴露了 CDP,因此自动化代码本身会继承过来。改变的是凭证的位置——Bright Data 将其放在 URL 的用户信息中,而 Scrapeless 则放在查询参数中。
python
import os
from playwright.sync_api import sync_playwright
# Bright Data (illustrative):
# wss://<username>:<password>@brd.superproxy.io:9222
endpoint = f"wss://browser.scrapeless.com/api/v2/browser?token={os.environ['SCRAPELESS_API_KEY']}"
with sync_playwright() as p:
browser = p.chromium.connect_over_cdp(endpoint)
page = browser.new_page()
page.goto("https://quotes.toscrape.com/", wait_until="domcontentloaded")
print("title:", page.title())
print("quotes on page:", len(page.query_selector_all(".quote")))
browser.close()
这个位置变化有一个值得规划的操作后果。许多记录和追踪库会自动去除 URL 用户信息,但会保留查询字符串,因此一个之前默认被遮蔽的连接字符串可能开始出现在日志中。在你发布之前,先对 token 参数进行过滤。
在开始之前要考虑两个大小限制:Scrapeless Scraping Browser 仅支持 CDP,因此 Selenium 套件是重写而不是重新指向,且 connect_over_cdp 附加到远程浏览器而不是启动一个,因此你当前代码中的任何 launch() 参数都没有目的地。
一个有效的迁移顺序
- 盘点你的区域,并将每个区域标记为解锁器形状或 SERP 形状。这是去复用步骤,也是唯一真正手动的部分。
- 首先迁移解锁器路径——它是一个头部变化加上信封解开,在一个助手中。
- 第二迁移 SERP 路径,切换到 v1 路径,并删除你的 URL 组装和 HTML 解析器。
- 最后重新指向浏览器自动化;这是最小的差异。
- 对相同的 URL 列表运行两个栈,并比较提取的字段,而不是原始字节。获取之间的标记无害地不同;提取的值不应不同。
清晰迁移的用例
- 价格和目录监控——解锁器形状,一个助手,最高量且最简单的环节。
- 排名追踪和 SERP 监控——增加结构化字段,失去 URL 组装。
- 代理和 RAG 检索管道——解析后的 SERP 输出直接进入一个检索步骤,去除了一个解析阶段而不是增加一个。
迁移不干净的案例是基于 Selenium 的浏览器套件,理由如上所述。单独预算,而不是将其纳入同一个冲刺。
定价比较
诚实的比较是结构性的而不是数字的。Bright Data 将费用归因于一个区域,因此支出按配置对象分组,跨越两个区域的一个作业会出现在两个地方。Scrapeless 将费用归因于对一个密钥的请求,因此归属遵循了发起调用的代码路径。
如果你部分迁移是为了成本可见性,这种差异比标题费率更重要。在建模任何内容之前,请查看 Scrapeless 定价页面 和 Bright Data 自身的定价页面上的当前数字。
相关资源
- 仍在选择而不是迁移?Bright Data 的代理替代品 比较按表面排名。
- 通用抓取 API 产品页面 全面记录了解锁器表面。
- Chrome DevTools 协议参考 涵盖了两个浏览器产品使用的传输格式。
结论
Bright Data 的迁移在差异大小上很小,且容易出现微妙错误。端点和密钥是可见的一半;导致调试周期成本的另一半是一个 Bright Data 端点映射到两个 Scrapeless 表面,主体是以包装形式到达的,并且这两个表面基于不同的 API 版本。首先迁移解锁器路径,将信封解开保留在单个助手中,并在切换时比较提取的字段而不是原始 HTML。
如果你的集成仍然在端口 22225 或 33335 上,则无论你最终选择哪个提供商,你的日历上都有最后期限。这是一个合理的时刻,可以在九月底的压力下,谨慎决定。
准备好迁移你的爬虫了吗?
在 Scrapeless 控制面板 创建一个密钥,并对你已经收集的一个 URL 运行上面的解锁器代码。比较提取的字段与当前输出之间的差异是一个十五分钟的测试,可以回答大多数迁移问题。
常见问题
问:Bright Data 的迁移实际需要多长时间?
对于仅解锁器集成,几个小时:一个头部变化,在一个助手中的信封解开,以及一次差异运行。SERP 路径通常比预期的要快,因为你删除的代码比你写的多——HTML 解析器和 URL 组装都要删除。Selenium 浏览器套件则是一个例外,需要单独进行规划。
问:我需要重新创建我的区域吗?
不 — 没有区域对象需要重建。一把钥匙覆盖每个表面。工作转移到你的代码中:每个区域必须被分类为解锁器形状或SERP形状,以便调用站点知道要连接哪一个端点。
问:我的Playwright或Puppeteer代码还会工作吗?
是的。两个提供者都暴露了CDP WebSocket,因此自动化体保持不变,只有连接字符串不同。Selenium是个例外:Scrapeless Scraping Browser仅支持CDP。
问:为什么我移植的代码返回空结果而没有抛出错误?
几乎总是响应信封的问题。Bright Data 使用 format: "raw" 返回页面主体,而Scrapeless返回包含在 data 内的JSON。将信封解析为HTML不会产生匹配项,也不会引发异常。将 response.text 改为 response.json()["data"]。
问:2026年9月25日会发生什么?
Bright Data的常见问题解答指出,端口 22225 和 33335 的证书将于当日00:00 UTC到期,流量必须迁移到端口 44445。这适用于继续使用Bright Data,也适用于离开,因此将其视为调度限制,而不是片面论证。
问:在切换过程中我可以同时运行两个提供者吗?
可以,这是推荐的方法。将两个路径放在一个接口后面,向每个路径发送样本流量,并比较提取的字段。根据作业进行切换,而不是一下子全部切换,从最高流量的解锁器工作负载开始。
在Scrapeless,我们仅访问公开可用的数据,并严格遵循适用的法律、法规和网站隐私政策。本博客中的内容仅供演示之用,不涉及任何非法或侵权活动。我们对使用本博客或第三方链接中的信息不做任何保证,并免除所有责任。在进行任何抓取活动之前,请咨询您的法律顾问,并审查目标网站的服务条款或获取必要的许可。



