OpenClaw 接入实时数据 API,才能从聊天框进化为真正的电商 AI 智能体
背景
最近社区里经常看到这类帖子:
"OpenClaw 部署好了,飞书机器人也配好了,结果问它选品,给我一堆废话,和 ChatGPT 没区别,是不是我哪里配置错了?"
没配错。问题不是配置,是认知——对 LLM + Agent 关系的认知,以及对数据在 Agent 工作流中角色的认知。
本文从原理出发,给出 OpenClaw 接入数据 API 的完整方案。
核心原理:Agent = LLM + Perception + Action
为什么"没有数据 = 没有 Agent"?
Agent 的学术定义很简单:能感知环境、基于感知做决策、并执行行动的系统。
关键词是"感知环境"。对于没有数据接入的 OpenClaw,它的感知范围只有:
- 用户当前输入的文本
- 训练集截止日期之前的世界状态
这意味着任何依赖"当下"信息的任务,它只能做推断,而不是感知。推断和感知之间的差距,就是"套壳 ChatGPT"和"真正 AI Agent"之间的差距。
LLM 能力边界图谱
Agent = LLM(大脑)+ Tools(手脚),缺失工具层的 OpenClaw 无法真正"感知"市场
LLM(大脑能力)
├── ✅ 可以做
│ ├── 推理与逻辑
│ ├── 文本理解与生成
│ ├── 代码生成
│ ├── 总结与归纳
│ └── 结构化输出
└── ❌ 不能做(需要 Tool)
├── 获取实时市场数据
├── 读取今天的 BSR 排名
├── 查询当前竞品价格
├── 知道本周上架了什么
└── 访问任何训练集截止后的信息
对于电商运营来说,几乎所有有价值的决策数据都在 ❌ 区间。这就是为什么完成 OpenClaw 接入数据 API 是前提而非可选项。
技术挑战:为什么亚马逊数据难以自建采集?
在介绍 Pangolinfo 接入方案之前,有必要说清楚为什么自建不值得:
挑战一:JavaScript 动态渲染
# 直接请求的问题
import requests
resp = requests.get(
"https://www.amazon.com/dp/B09G9FPHY6",
headers={"User-Agent": "Mozilla/5.0 ..."}
)
# 获取的 HTML 中,BSR、价格等关键数据往往不完整
# 因为这些数据通过 XHR/JS 异步加载
print(resp.text[:500]) # 大概率是空壳或 CAPTCHA 页面
需要:Playwright/Puppeteer + 等待策略 + 截图验证
挑战二:IP 封禁
亚马逊对数据中心 IP 的检测极为敏感:
# 这个请求从 AWS/GCP/Aliyun IP 发出,大概率会得到 CAPTCHA
resp = requests.get("https://www.amazon.com/dp/B09G9FPHY6")
# 响应可能是 503 / Robot Check / CAPTCHA HTML
需要:住宅代理 IP 池(月费 $200-1000+),且需要持续维护 IP 质量
挑战三:解析器维护
亚马逊页面结构频繁变化,XPath/CSS 选择器定期失效。每次变化都需要人工检查和修复。
成本汇总:
| 自建成本项 | 初期 | 持续 |
|---|---|---|
| 代理 IP | $200-800/月 | 持续 |
| 工程师初始开发 | 2-4 周 | - |
| 解析器维护 | - | 每月 2-8 小时 |
| 基础设施(服务器) | $50-200/月 | 持续 |
Pangolinfo Scrape API 接入方案
先说一个 Agent 时代的好消息
很多人看到"接入 API"就头疼——担心要研究文档、写调用代码、处理各种边界情况。
Agent 时代,这件事已经大幅简化了。
你只需要做一件事:把以下两样东西给 OpenClaw:
- 📄 Pangolinfo 文档:docs.pangolinfo.com
- 🔑 API Key:从 Pangolinfo 控制台 获取
告诉 OpenClaw 目标是"接入 Pangolinfo 亚马逊数据采集能力",它会自动读取文档、理解接口规范,完成全自动接入。不需要你手动写一行集成代码。
这就是 Agent 时代的正确姿势:Agent 自己集成自己的工具。
当然,如果你希望对集成细节有完整掌控,下面是完整的手动接入方案:
架构位置
OpenClaw Agent
│
▼ 触发工具调用
PangolinAmazonTool.get_product(asin)
│
▼ POST /api/v1/scrape
Pangolinfo API Gateway
│ 代理池选择 + 任务分发
▼
渲染集群(住宅 IP + 无头浏览器)
│
▼
Amazon 商品页面 → 结构化 JSON 解析
│
▼ 结构化 JSON 响应
OpenClaw Agent(LLM 分析 → 输出报告)
完整实现代码
"""
openclaw_amazon_tool.py
OpenClaw 数据工具:Pangolinfo Amazon Scraper API 完整实现
支持同步单品查询和异步批量分析
"""
import asyncio
import aiohttp
import requests
from urllib.parse import urljoin
from typing import Optional
from dataclasses import dataclass, field
API_ENDPOINT = "https://scrapeapi.pangolinfo.com/api/v1/scrape"
@dataclass
class AmazonProduct:
"""亚马逊商品数据结构化模型"""
asin: str
title: str = ""
price: Optional[float] = None
currency: str = "USD"
bsr: Optional[int] = None
bsr_category: str = ""
rating: Optional[float] = None
review_count: Optional[int] = None
buy_box_seller: str = ""
buy_box_price: Optional[float] = None
in_stock: bool = False
seller_count: Optional[int] = None
image_url: str = ""
scraped_at: str = ""
error: str = ""
@property
def is_valid(self) -> bool:
return not self.error and self.price is not None
def to_markdown(self) -> str:
"""生成 Markdown 格式报告,可直接传入 OpenClaw Agent 上下文"""
if self.error:
return f"**{self.asin}**: 数据获取失败 — {self.error}"
lines = [
f"### {self.asin}",
f"**商品**: {self.title[:80]}",
f"**价格**: ${self.price} {self.currency}",
f"**BSR**: #{self.bsr:,} in {self.bsr_category}" if self.bsr else "**BSR**: N/A",
f"**评分**: {self.rating}/5.0 ({self.review_count:,} 条评论)" if self.review_count else "**评分**: N/A",
f"**Buy Box**: {self.buy_box_seller} @ ${self.buy_box_price}" if self.buy_box_seller else "**Buy Box**: 未知",
f"**库存**: {'✅ 有货' if self.in_stock else '❌ 无货'}",
f"**第三方卖家数**: {self.seller_count}",
f"*数据时间: {self.scraped_at}*"
]
return "\n".join(lines)
class PangolinAmazonScraper:
"""
Pangolinfo Amazon Scraper API 封装
作为 OpenClaw AI Agent 的数据感知层
"""
def __init__(self, api_key: str, max_concurrent: int = 5):
self._headers = {
"Content-Type": "application/json",
"Authorization": f"Bearer {api_key}"
}
self._sem = asyncio.Semaphore(max_concurrent)
# --------------------------------------------------
# 同步接口(单品查询)
# --------------------------------------------------
def get(self, asin: str, country: str = "us") -> AmazonProduct:
"""
同步查询单个 ASIN
Args:
asin: 亚马逊商品 ID
country: 站点代码(us/uk/de/jp/ca/fr 等)
"""
try:
resp = requests.post(
API_ENDPOINT,
headers=self._headers,
json=self._build_payload(asin, country),
timeout=30
)
resp.raise_for_status()
result = resp.json()
if result.get("code") != 0:
return AmazonProduct(asin=asin, error=result.get("message", "API Error"))
return self._parse(asin, result["data"])
except requests.exceptions.Timeout:
return AmazonProduct(asin=asin, error="请求超时(>30s),建议重试")
except Exception as e:
return AmazonProduct(asin=asin, error=str(e))
# --------------------------------------------------
# 异步接口(批量查询,生产推荐)
# --------------------------------------------------
async def _get_async(
self,
asin: str,
country: str,
session: aiohttp.ClientSession
) -> AmazonProduct:
async with self._sem:
try:
async with session.post(
API_ENDPOINT,
headers=self._headers,
json=self._build_payload(asin, country),
timeout=aiohttp.ClientTimeout(total=30)
) as resp:
result = await resp.json()
if result.get("code") != 0:
return AmazonProduct(asin=asin, error=result.get("message"))
return self._parse(asin, result["data"])
except Exception as e:
return AmazonProduct(asin=asin, error=str(e))
def batch(
self,
asins: list[str],
country: str = "us",
sort_by: str = "bsr" # 可选: "bsr" / "rating" / "review_count"
) -> list[AmazonProduct]:
"""
批量查询,支持排序
Args:
asins: ASIN 列表
country: 站点代码
sort_by: 排序字段
"""
async def _run():
connector = aiohttp.TCPConnector(limit=10)
async with aiohttp.ClientSession(connector=connector) as sess:
tasks = [self._get_async(a, country, sess) for a in asins]
return await asyncio.gather(*tasks)
results = list(asyncio.run(_run()))
valid = [r for r in results if r.is_valid]
failed = [r for r in results if not r.is_valid]
# 排序
sort_map = {
"bsr": lambda x: x.bsr or 9_999_999,
"rating": lambda x: -(x.rating or 0),
"review_count": lambda x: -(x.review_count or 0)
}
valid.sort(key=sort_map.get(sort_by, sort_map["bsr"]))
return valid + failed
# --------------------------------------------------
# 私有方法
# --------------------------------------------------
def _build_payload(self, asin: str, country: str) -> dict:
return {
"url": f"https://www.amazon.{country}/dp/{asin}",
"parserName": "amazonProduct",
"country": country
}
def _parse(self, asin: str, data: dict) -> AmazonProduct:
price_info = data.get("price", {})
bsr_list = data.get("bestSellersRank", [])
buybox = data.get("buyBox", {})
return AmazonProduct(
asin=asin,
title=data.get("title", ""),
price=price_info.get("current"),
currency=price_info.get("currency", "USD"),
bsr=bsr_list[0].get("rank") if bsr_list else None,
bsr_category=bsr_list[0].get("category", "") if bsr_list else "",
rating=data.get("rating"),
review_count=data.get("reviewCount"),
buy_box_seller=buybox.get("seller", ""),
buy_box_price=buybox.get("price"),
in_stock=data.get("availability") == "In Stock",
seller_count=data.get("offerCount"),
image_url=data.get("image", ""),
scraped_at=data.get("scrapedAt", "")
)
# ==================== OpenClaw 集成使用示例 ====================
if __name__ == "__main__":
scraper = PangolinAmazonScraper(api_key="YOUR_PANGOLINFO_API_KEY")
# 竞品对比分析
competitor_asins = [
"B09G9FPHY6",
"B0BTSR8T9M",
"B0CKQSQ2WS",
"B099WMYZ8P",
"B0BN7C9T3D"
]
print("正在获取实时竞品数据...\n")
results = scraper.batch(competitor_asins, country="us", sort_by="bsr")
# 生成传入 OpenClaw Agent 的 Markdown 上下文
agent_context = "\n\n".join([r.to_markdown() for r in results])
print("=== 传入 OpenClaw Agent 的实时竞品数据 ===\n")
print(agent_context)
# 然后将 agent_context 传入 OpenClaw Agent,
# 让 LLM 基于真实数据进行分析,输出选品建议
最佳实践
并发控制
max_concurrent=5是大多数账户的安全值- 高频批量场景可与 Pangolinfo 确认账户并发上限
缓存策略
- 热门 ASIN 建议设置 30-60 分钟缓存
- 价格监控场景:缓存 TTL 10-15 分钟,保持时效性
错误处理
- 所有错误以
AmazonProduct(error=...)形式返回,不会中断批量流程 - 生产环境建议加指数退避重试(最多3次)