CrewAI 工具实战:OxylabsAmazonSearchScraperTool 采集 Amazon 搜索结果
OxylabsAmazonSearchScraperTool 是 crewAI 官方 crewai-tools 包中面向亚马逊(Amazon)搜索结果页的数据采集工具,它把 Oxylabs 爬虫 API 封装成可供 Agent 直接调用的 CrewAI 工具,让 AI Agent 能像调用普通函数一样拉取指定关键词的 Amazon 搜索页内容。读完本文,你将掌握该工具的安装方式、基于环境变量的快速接入、完整配置项含义与进阶用法,并从源码层面理解它的凭据解析、SDK 客户端初始化与结果格式化等底层机制,从而在自己的 CrewAI 应用里正确、稳定地使用它。
工具定位与适用场景
从源码类定义可以看出,该工具本质上是一个 crewai.tools.BaseTool 的子类(oxylabs_amazon_search_scraper_tool.py):
name: str = "Oxylabs Amazon Search Scraper tool"
description: str = "Scrape Amazon search results with Oxylabs Amazon Search Scraper"
args_schema: type[BaseModel] = OxylabsAmazonSearchScraperArgs
其中:
name与description是给 LLM 看的“工具说明书”,用于在 Agent 执行任务时自动识别该工具是否适用——即“抓取 Amazon 搜索结果”;args_schema声明了工具入参为OxylabsAmazonSearchScraperArgs,其唯一字段是query,注释为 "Amazon search term",也就是说运行该工具只需一个搜索关键词即可;- 该类在 tools/init.py 中随
crewai_tools包顶层一并导出,因此用户可直接通过from crewai_tools import OxylabsAmazonSearchScraperTool导入。
典型的适用场景包括:商品价格与库存调研、竞品关键词监测、市场行情分析,或是把爬取到的搜索页数据作为上下文继续交给其他 Agent / LLM 做二次加工。
安装依赖
使用该工具需要同时安装 CrewAI 工具集和 Oxylabs 官方 Python SDK:
pip install 'crewai[tools]' oxylabs
crewai[tools] 负责提供 BaseTool、EnvVar 等工具底座,oxylabs 则是实际发起爬虫请求的客户端库。从源码可以看到,工具运行期会真正依赖 oxylabs.RealtimeClient 与 oxylabs.sources.response.Response 这两个模块(oxylabs_amazon_search_scraper_tool.py):
try:
from oxylabs import RealtimeClient
from oxylabs.sources.response import Response as OxylabsResponse
OXYLABS_AVAILABLE = True
except ImportError:
...
OXYLABS_AVAILABLE = False
若实例化时发现 oxylabs 未安装,工具会弹出交互式确认框询问是否自动安装,确认后执行 uv add oxylabs,失败则抛出 ImportError,提示手动执行 uv add oxylabs。因此提前安装依赖可以避免运行期的交互中断。
快速开始
准备一个 Oxylabs 账号并取得用户名与密码后,即可使用。工具支持两种凭据注入方式,其中推荐在环境变量中声明,便于统一管理密钥:
from crewai_tools import OxylabsAmazonSearchScraperTool
# make sure OXYLABS_USERNAME and OXYLABS_PASSWORD variables are set
tool = OxylabsAmazonSearchScraperTool()
result = tool.run(query="headsets")
print(result)
在没有显式传参时,工具会回退读取 OXYLABS_USERNAME 与 OXYLABS_PASSWORD 两个环境变量。如果两个来源都拿不到凭据,构造时会直接抛出 ValueError,提示用户“实例化时传入用户名密码,或设置这两个环境变量”(见 源码 _get_credentials_from_env)。
此外,该工具在类上通过 env_vars 字段声明了两个必填环境变量(源码 L79-L92):
env_vars: list[EnvVar] = Field(
default_factory=lambda: [
EnvVar(name="OXYLABS_USERNAME", description="Username for Oxylabs", required=True),
EnvVar(name="OXYLABS_PASSWORD", description="Password for Oxylabs", required=True),
]
)
这份声明是给 CrewAI 运行环境(如托管平台、配置面板)看的元数据,用于告知平台该工具必须注入哪两个密钥。
需要说明的是:在命令行终端里直接设置环境变量即可运行,例如
export OXYLABS_USERNAME="你的用户名"与export OXYLABS_PASSWORD="你的密码"。若在 Jupyter/脚本中,也可在进程内用os.environ预置这两个键。
初始化参数:username 与 password
工具构造函数签名如下(源码 L94-L100):
def __init__(
self,
username: str | None = None,
password: str | None = None,
config: OxylabsAmazonSearchScraperConfig | dict[str, Any] | None = None,
**kwargs: Any,
) -> None:
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
username |
str |
否(二选一) | Oxylabs 账号用户名;不传则读取 OXYLABS_USERNAME 环境变量 |
password |
str |
否(二选一) | Oxylabs 账号密码;不传则读取 OXYLABS_PASSWORD 环境变量 |
config |
OxylabsAmazonSearchScraperConfig 或 dict |
否 | 爬取行为配置,如站点、翻页、解析策略等,见下文配置表 |
凭据解析遵循“显式参数优先,环境变量兜底”的原则:只有两者都为空时才回退环境变量,全部缺失即抛错。这里还隐藏着一个细节:初始化时工具会用 oxylabs-crewai-sdk-python/<crewai 版本> (<Python 版本>; <平台位数>) 拼接一段 SDK 标识(源码 L101-L106),在创建 Oxylabs RealtimeClient 时通过 sdk_type 参数上报给服务端,便于 Oxylabs 侧识别流量来源。
完整配置项解析
除 query 之外的所有抓取细节都通过 config 控制。源码用 Pydantic 模型 OxylabsAmazonSearchScraperConfig(L32-L53)定义了以下可选字段,config 既可以传 dict,也可以直接传该模型对象——由于类字段已声明为该 Config 类型且开启了 validate_assignment,传入的字典会自动被 Pydantic 校验并归一化为模型:
| 配置字段 | 类型 | 含义(取自源码字段注释) |
|---|---|---|
domain |
str | None |
限定搜索结果归属的 Amazon 站点域名,例如 "nl"、"co.uk" |
start_page |
int | None |
抓取的起始页码 |
pages |
int | None |
需要抓取的页数 |
geo_location |
str | None |
“配送至”地理位置(Deliver to location),影响结果的本地化呈现 |
user_agent_type |
str | None |
设备类型与浏览器(Device type and browser) |
render |
str | None |
是否启用 JavaScript 渲染(应对动态加载页面) |
callback_url |
str | None |
异步结果的回调端点地址,适合耗时任务通过 Webhook 接收结果 |
context |
list[Any] | None |
面向特殊需求的高级设置与控制项列表(如站点分类过滤) |
parse |
bool | None |
置为 True 时返回结构化数据 |
parsing_instructions |
dict[str, Any] | None |
自定义解析结果的指令 |
这些配置会在真正发请求时通过 self.config.model_dump(exclude_none=True) 展开为关键字参数传递给 Oxylabs 的 amazon.scrape_search(见下文“底层调用链”),exclude_none=True 意味着未设置的字段一律不会出现在请求参数里,只有显式配置项才会生效。
进阶用法示例
下面的进阶示例展示了常见配置组合:限定荷兰站(domain='nl')、从第 2 页开始连续抓取 2 页、开启结构化解析,并通过 context 传入一个站点分类 ID 来进一步过滤结果(对应 README 原例,完整收录如下):
from crewai_tools import OxylabsAmazonSearchScraperTool
# make sure OXYLABS_USERNAME and OXYLABS_PASSWORD variables are set
tool = OxylabsAmazonSearchScraperTool(
config={
"domain": 'nl',
"start_page": 2,
"pages": 2,
"parse": True,
"context": [
{'key': 'category_id', 'value': 16391693031}
],
}
)
result = tool.run(query='nirvana tshirt')
print(result)
示例要点:
domain用于做地域站点的横向选择,适合多站点比价类任务;start_page与pages组合即可实现翻页抓取,弥补单页数据不足的问题;parse=True让服务端直接返回结构化字段(如商品标题、价格),而非原始 HTML,能显著降低后续 Agent 解析成本;context以{'key': ..., 'value': ...}键值对列表的形式传入,用于承载如品类 ID 等高级过滤条件,具体支持的 key 取决于 Oxylabs 服务端能力,可按需查阅 Oxylabs 的 Amazon Search 目标参数文档确认。
除了 context 这种字典写法,config 同样支持直接实例化 Config 模型后传入,例如测试代码中使用过 config={"domain": "co.uk"}、OxylabsGoogleSearchScraperConfig(render="html") 等混合传参方式(见 test_oxylabs_tools.py),两种形式对该工具一律适用,效果等价。
源码级原理:底层调用链与返回格式
为了更稳妥地接入 Agent 工作流,有必要理解 run 触发后发生了什么。其核心执行逻辑位于 _run(oxylabs_amazon_search_scraper_tool.py L157-L168):
def _run(self, query: str) -> str:
response = self.oxylabs_api.amazon.scrape_search(
query,
**self.config.model_dump(exclude_none=True),
)
content = response.results[0].content
if isinstance(content, dict):
return json.dumps(content)
return str(content)
可以拆解为三步:
- 调用 Oxylabs 专用端点:
RealtimeClient.amazon.scrape_search(query, **配置)是针对 Amazon 搜索场景封装的专用方法,与通用scrape_url区分开;所有非空配置展开为关键字参数随请求一起发送。 - 读取首个结果内容:
response.results[0].content取回第一条结果的正文,其结构取决于请求参数:启用parse=True时通常为字典形态的结构化数据,否则多为原始 HTML 字符串。 - 统一返回字符串:为保证 Agent 拿到的永远是文本,字典内容会被
json.dumps序列化为 JSON 字符串;HTML 等其他内容则直接str()转换后返回。
这一点在测试中也有对应断言(test_oxylabs_tools.py L152-L158):mock 一个返回 JSON 字典、一个返回 HTML 字符串,分别断言结果可被 json.loads 解析为 dict、以及结果包含 <!DOCTYPE html>。这从测试层面验证了“结构化 JSON / 原始 HTML 两种返回都成立”的事实——因此下游 Agent 在消费结果时应当兼容这两种形态,或用 parse=True 锁定结构化输出。
同族工具与组合使用
Oxylabs 系列工具在 crewai-tools 中并不是孤立的。根据 tools/init.py 的导出及 test_oxylabs_tools.py 的导入可见,同批还提供了:
OxylabsAmazonProductScraperTool:抓取单个 Amazon 商品详情页;OxylabsGoogleSearchScraperTool:抓取 Google 搜索结果;OxylabsUniversalScraperTool:通用 URL 抓取。
它们共享同一套凭据(OXYLABS_USERNAME / OXYLABS_PASSWORD)、同样的 Config 校验模型以及同源 mock 测试夹具,因此一旦跑通本文的 Search 工具,其余三者几乎零成本上手。测试文件也覆盖了这四类工具的通用行为:带参初始化、环境变量初始化、凭据缺失抛 ValueError、以及 JSON/HTML 两种返回的调用成功路径(test_oxylabs_tools.py L72-L158)。在真实 Agent 编排中,完全可以把 Search(搜词)、Product(取详情)串成一条“发现商品 → 深挖详情”的复合任务链。
使用注意与建议
结合源码实现,实际使用时有几点值得留意:
- 凭据必须可解析:要么显式传
username/password,要么确保两个环境变量均已设置,否则构造即抛ValueError;不要在生产环境中把密钥硬编码进config。 - 保持环境干净:工具要求宿主机安装了
oxylabsSDK,若缺失会触发交互式安装询问,在无交互的 CI/Agent 进程中可能直接失败,务必在安装阶段先执行pip install 'crewai[tools]' oxylabs。 - 按需开启解析:
parse=True虽然返回结构化 JSON 更利于 LLM 消费,但解析字段是服务端预设的;如需完全自定义字段,可结合parsing_instructions下发解析规则。 - 区分同步与异步:
callback_url用于把结果推送到你的回调端点,适合批量翻页或大量关键词的耗时场景;不设置时走同步等待路径。 - 翻页参数配合使用:
start_page单独使用没有意义,通常与pages成对出现以控制抓取范围,同时也影响请求量与计费。 - 返回形态自适应:代码与测试都证明输出可能是 JSON 字符串或原始 HTML 字符串,Agent 在解析前应先做形态判断,或统一开启
parse=True。
最后提醒:抓取 Amazon 等站点务必遵守目标网站的 robots 协议、相关法律法规以及 Oxylabs 服务条款,仅在合规授权范围内使用采集能力。
延伸阅读:可在仓库内进一步阅读该工具完整实现 oxylabs_amazon_search_scraper_tool.py、官方 README,以及覆盖整个 Oxylabs 工具族的测试 test_oxylabs_tools.py 作为接入参考。
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0630
MiniCPM5-2BMiniCPM5-2B 是一款面向端侧、本地部署和资源受限场景的 2B 稠密 Transformer,能够达到同尺寸开源模型 SOTA 水平。Markdown00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
GLM-5.3-FlashGLM-5.3-Flash (320B-A18B),是GLM-5系列的首个原生多模态模型。320B总参数,能力超过GLM-5.2Jinja00
Spark-X2.5-4BSpark-X2.5-4B 旨在让强大的 AI 更实用、更高效、更易获得。在广泛日常任务中表现强劲,涵盖对话、写作、翻译、推理、编码、工具调用以及智能体工作流,并在同等规模的开源模型中取得领先成绩。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00