Idealo 商家报价 API:先筛选商品,再补全报价,减少无效调用

发布于 2026年10月17日

offers_count: 512,这是一次德国站搜索中首条商品的报价数量,不是已经拿到手的 512 行商家数据。准备做竞品价格监控时,先别把这列接进调价引擎:真正影响请求预算的,是哪些商品值得继续查。

offers_count 是 512,为什么 offers 仍是空数组

已验证的 iphone 16 搜索返回 36 条商品摘要。首条 ID 为 204736899,同时出现 offers_count=512 和 offers=[]。这不是“没有商家”,也不表示应该反复重试关键词搜索;search-by-term 本来就只负责发现候选商品,提供名称、最低价、图片和报价数量,不返回逐店报价。

要拿商家明细,应把筛选后的国家与商品 ID 交给 search-by-id。另一项已验证的 ID 查询使用 204771161,返回 20 行报价;它不是首条 204736899,不能把两次观察拼成“512 条报价只返回了 20 条”。

这里读取的是商品与竞品报价观察,不是管理自家店铺报价的商家接口,不会上传报价、修改售价或下单。

一次搜索加三个商品补全:至少需要八次调用

假设先发现候选,再选三个 ID,每个任务至少创建一次、取回一次:

请求用途创建任务获取结果最少调用
一次关键词搜索112
三个 ID 分别补全336
合计448

若把上述 36 条结果全部补全,下限就是 2 + 36 × 2 = 74 次,而不是八次。两种算法都只是网络调用下限,不是点数报价,也不是完成时间承诺;任务尚未结束时,每多轮询一次就再增加一次请求。

选品看板只需要最低价和竞争密度,可以停在摘要层。只有型号、规格符合目标的条目才进入监控池;已有审核通过的国家与 ID 映射,也不必每轮从关键词重新找起。一次关键词能返回很多条目,不代表 values 支持批量输入。

先确定国家与商品 ID,再请求报价详情

国家只接受德国 de、奥地利 at;成功实测仅覆盖 de,不能据此宣称奥地利站也已验证。保存 (country, id),不要只按相似商品名关联。ID 使用字符串,不能为零或以零开头。

四个 POST 查询都只有一个必填字符串参数 body,其内容才是含 country、values 的 JSON 文本。values 必须恰好包含一个字符串。直接调用网关时,不能把这两个内层字段平铺到请求顶层。

下面是关键词任务模板,不是立即读取某件商品的请求。先填写自己的平台 API 密钥,并有意替换 body 内的占位词;例如内层文本可用 {"country":"de","values":["iphone 16"]}。密钥留在服务端或受控环境中,查询参数须从日志中脱敏。打开页面、展开说明或复制模板不会发送请求;主动提交才会创建临时采集任务、使用一次请求。

curl --request POST \
  'https://api.opendata-api.com/api/project/idealo/search-by-term?key=YOUR_API_KEY' \
  --header 'Content-Type: application/json' \
  --data '{"body":"{\"country\":\"de\",\"values\":[\"REPLACE_WITH_SEARCH_TERM\"]}"}'

提交成功后保存新的 job_id。候选经审核,再以同样的字符串封装向 search-by-id 提交选中的 ID。若已有商品链接,可考虑文档中的 search-by-url,但链接必须与国家一致;该路线尚未实测,不能照搬 ID 查询的成功结论。

等任务进入终态,再启动下一阶段

HTTP 200 不是找到商品。若响应有 code/message/data 封装,逐层检查业务码;非 200 先处理错误,再读取成功载荷。创建响应中的 error=false 与 job_id 只表示接受任务,不含即时商品详情。

用刚创建的 ID 取结果,不要复制过去的任务编号:

curl 'https://api.opendata-api.com/api/project/idealo/get-job?key=YOUR_API_KEY&job_id=REPLACE_WITH_FRESH_JOB_ID'

轮询可从约五秒间隔起步,再退避,并设置截止时间和总调用上限;达到任一上限就暂停调度,保留任务 ID 供后续处理,而不是再次创建同样任务。

pending 不启动补全;failed 进入错误处理。completed 后仍要逐条检查 found、not_found、error:已验证的无意义关键词就曾正常完成,却返回 not_found、result:null。只有通过审核的 found 条目进入下一阶段。若条目报告 invalid_query,先修输入,不要盲目重试。

确认同款与规格后,再比较含运费总价

有 EAN 或 GTIN 时可用 search-by-gtin,但条码不是免审凭证。输入须为 8–14 位数字字符串,保留前导零;这是条码规则,不是商品 ID 规则。

已验证的 Nutella 条码任务对应 450g 产品,却混入 15 × 450g 多件装,即便它也标为 classification:product_page_match、confidence:high。把多件装总价与单罐比,会制造虚假的价差;先核对标题、型号、容量、颜色及包装数量,再按已确认的数量计算单位成本。

商家比较要同时看 currency、price、shipping、total,以及成色和可用性,不能只按商品价排序。运费未知不等于包邮,空字段也不应补成零。上述 204771161 在搜索摘要中计数 82,明细实际返回 20 行;这些报价不是全量覆盖证明,也不是固定返回上限。

保存 fetched_at 快照,不把接口当作历史价格库

任务结果在完成后仅保留一小时,应在窗口内取回并落库。created_at 是任务创建时间,商品 fetched_at 才是这次价格观察的时间,二者不要混用。

记录国家、查询值、操作、返回 ID、规格审核结论与原始报价,保留 null。历史价格需要应用定期创建新任务、保存带时间的快照;get-job 不是历史价格查询接口。缓存复用多久应由业务的新鲜度要求决定,不能把旧快照展示成当前可成交价。

避免浪费调用和错误比价的几个常见问题

  • 发现一条就补全一条。 先在本地排除不匹配型号、重复候选和不关心的规格,再分配请求预算。
  • 把多个 ID 塞进 values 省请求。 每个任务只接受一个值;列表不等于批处理能力。
  • 将未找到记为零元。 completed 只说明处理结束,not_found 是缺失观察,不是免费商品。
  • 拿旧任务或 ping 证明采集正常。 历史任务会过期;ping 仅是文档中的存活检查,且未实测,不能证明报价获取、匹配或价格新鲜度正常。