mcpField
I
israeli-grocery-price-intelligence

israeli-grocery-price-intelligence

github.com/skills-il数据与数据库5159 次安装7 周前更新
代码仓库

关于 israeli-grocery-price-intelligence

israeli-grocery-price-intelligence 是利用以色列零售连锁公开数据源或现有 MCP 服务分析食品杂货价格的技能。它指导数据源访问、XML 解析、价格归一化和跨连锁比较;无需自动化时也会推荐现有比价应用。

主要功能

  1. 01选择消费应用或原始数据源
  2. 02访问各连锁专属价格数据源
  3. 03解析并归一化 XML 价格
  4. 04合并完整快照与增量文件
  5. 05跨连锁比较商品

适用场景

  1. 01自动比较购物清单总价
  2. 02构建自定义购物清单优化器
  3. 03跟踪价格变化趋势
  4. 04分析餐厅食材成本

MCP 相关

安装 supermarket-prices MCP 服务时,该技能会引导 Agent 使用其工具查询连锁、搜索商品、比较价格、查看促销和门店数据及 XML 参考资料。未安装时则介绍手动处理 XML 数据源的方法。

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/skills-il/food-and-dining --skill israeli-grocery-price-intelligence

安装后在 Claude Code 中输入/israeli-grocery-price-intelligence确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

CHANGELOG.md
evidence.json
metadata.json
optimization-log.json
SKILL_HE.md
references/
chain-feeds.md
domain-checklist.md
scripts/
parse_price_xml.py

详细介绍

以色列杂货价格情报

说明

非开发者最快上手方式:现成的比价应用

如果用户只是想知道某件商品或一篮子商品在哪里最便宜(而不是要构建自动化工作流),推荐他们使用已经能解析这些数据源的消费者比价服务,无需编写代码:

当用户需要自动化、自定义购物清单优化器、趋势跟踪或消费者应用不支持的餐厅成本分析时,再使用下方的原始数据源 / MCP 路径。

首选(用于自动化):使用 Supermarket Prices MCP Server

如果用户已安装 supermarket-prices MCP 服务,请使用它,而不是手动获取 XML 数据源。MCP 会自动处理身份验证、CSRF 令牌、SSL 问题和平台特性。

安装说明:https://agentskills.co.il/he/mcp/supermarket-prices

可用的 MCP 工具:

  • list_chains -- 列出所涵盖的连锁商店及其数据源信息(web / publishprice / FTP)
  • search_products -- 按商品名称或条形码搜索
  • compare_prices -- 跨连锁商店比价,并按价格从低到高排序
  • get_promotions -- 获取各连锁商店当前的促销和优惠
  • get_store_data -- 获取门店位置,可按城市筛选
  • get_chain_files -- 浏览原始 XML 价格文件
  • get_xml_schema_info -- 查看 XML 架构和字段的参考文档

如果 MCP 可用,请跳过步骤 1-2,直接使用 MCP 工具完成步骤 3-6。如果尚未安装 MCP,请改用下方的手动 XML 数据源方式。

步骤 1:访问超市 XML 数据源(手动备用方案)

根据《食品和药品行业促进竞争法》(חוק קידום התחרות בענפי המזון והפארם,2014 年通过,2015 年起生效),拥有 3 家及以上门店的以色列超市和药房连锁必须以 XML 文件形式公布商品价格。法律名称中的“药品”是 Super-Pharm 和 Good Pharm 也会发布数据的原因,但药房数据源仅涵盖药妆商品 SKU(洗漱用品、非处方药、婴儿食品),不包括生鲜农产品或乳制品。

  • 各连锁商店可用的数据文件(文件名前缀遵循政府规范):

    • PriceFull -- 包含商品目录及价格的完整快照
    • Price -- 完整快照之间的增量更新
    • PromoFull + Promo -- 当前促销和优惠的完整快照及增量更新
    • StoresFull + Stores -- 门店位置和详情
  • 不要使用正则表达式匹配文件名格式。 目前有两种格式,并非按平台清晰划分,单个连锁商店的文件列表中也可能同时出现两种格式:

    • 3 段格式:PriceFull<ChainId>-<StoreId>-<yyyyMMddHHmm>.gz
    • 5 段格式:PriceFull<ChainId>-<SubChainId>-<StoreId>-<yyyyMMdd>-<HHmmss>.gz

    一个正在使用的 Rami Levy 列表(Cerberus)中有 44 个采用 3 段格式的 PriceFull 文件,以及 93 个采用 5 段格式的文件;较新的文件使用 5 段格式。Shufersal 和 Carrefour 也使用 5 段格式。Stores 文件使用独立的 4 段格式,通常是普通的 .xml 文件。即使在同一个列表中,前缀的大小写也不一致(price、Price、pricefull、PriceFull),因此应忽略大小写进行匹配,并从右向左按位置解析,而不要假定段数固定。两种格式都不以 .xml.gz 结尾。 优先匹配较长的前缀。 不区分大小写的 startswith("price") 也会匹配所有 PriceFull,startswith("promo") 也会匹配所有 PromoFull,因此为增量文件编写的筛选器会悄悄地把完整快照也读入。应先检查 pricefull / promofull,再回退检查 price / promo

  • 每家 STORE 发布一个文件,而不是每条连锁发布一个文件。 不存在连锁级别的文件:拥有数百家分店的连锁每天会为每家分店发布一个 PriceFull。随便获取一个文件就称其为“Shufersal 的价格”是不对的;每个合并后的数据集都需要以 (ChainId, SubChainId, StoreId, ItemCode) 为键,这些值应从文件自身的根元素读取。这个元组也用于关联回 Stores 数据源,以获取分店地址,这样才能提供任何“附近”查询结果。

  • 完整快照通常每天刷新一次(夜间,IL 时间 01:00-05:00);增量文件每天可能推送多次

  • Shufersal 下载链接是有时限的签名 URL。 门户根页面只是浏览器 UI。使用 GET https://prices.shufersal.co.il/FileObject/UpdateCategory?catID=<N>&storeId=0 列出文件(catID=1 为 Price,2 为 PriceFull,3 为 Promo,4 为 PromoFull,5 为 Stores),然后从 HTML 中提取 pricesprodpublic.blob.core.windows.net 链接。这些链接包含一个 se= 到期时间,通常约半小时后到期;到期时间锚定在时钟边界,而非从你的请求时间开始计算,因此实际可用时限可能短得多。请尽快获取,切勿缓存或添加书签。

  • Carrefour 会在门户 HTML 中以内嵌 JavaScript files 数组的形式提供文件列表,并附带 yyyyMMdd 格式的 path;请从 https://prices.carrefour.co.il/<path>/<filename> 下载。错误的文件名会返回真实的 404。

  • 各连锁的端点、访问方式和 Cerberus 身份验证详见 references/chain-feeds.md

各连锁通过多个平台发布数据,不是一个,也不是三个。每个平台都有自己的访问机制。将连锁路由到错误的平台,是 Agent 报告“这家连锁什么都没发布”的最常见原因。下表已于 2026-08-27 通过实时探测验证;请将其作为起点,并重新探测,不要想当然:

平台URL已验证在该平台发布的连锁访问方式
Shufersal Directhttps://prices.shufersal.co.ilShufersal公开列表页;下载链接是会过期的签名 URL(见下文)
Carrefour Israel Directhttps://prices.carrefour.co.ilCarrefour Israel(Carrefour / Mega / Yeinot Bitan 品牌门店)公开;文件列表内嵌在页面中,下载地址为 /<yyyyMMdd>/<filename>
Cerberus (PublishedPrices)https://url.publishedprices.co.il/loginRami Levy、Yochananof、Tiv Taam、Osher Ad、Dor Alon、Keshet Taamim、Fresh Market / Super Dosh、Cofix (SuperCofixApp)会话登录 + CSRF(见下文)
Super-Pharm 自有门户http://prices.super-pharm.co.ilSuper-Pharm公开列表页
Bina Projectshttps://goodpharm.binaprojects.com/Main.aspxGood Pharm,以及几家小型连锁(King Store、Shuk Ahir、Zol VeBegadol、Bareket)各连锁子域名上的公开列表页
连锁自有网站https://shop.hazi-hinam.co.il/PricesHazi Hinam公开文件表

不在 Cerberus 上的连锁,尽管它们经常被列在那里。 使用 Victory、SuperPharm、GoodPharm、Bareket 或 Mega 登录 Cerberus 会失败(POST 返回 200 并重新呈现登录表单,而有效连锁代码会返回 302)。HaziHinam 可以登录,但其目录列表为空,而其自有网站提供完整的文件表。不要仅凭 Cerberus 登录失败就断定某家连锁已停止发布;应先查找其自有门户。 Victory 和 Mahsani A'Shuk 已从已停运的 Nibit 平台迁移到后继端点 (laibcatalog.co.il)。该主机可以解析,但在 2026-08-27 的探测中未接受连接,因此我们也无法确认它目前的状态。依赖它之前,请自行验证。 旧的 matrixcatalog.co.il 主机已完全无法解析(NXDOMAIN,并非超时)。

Cerberus 需要真正的身份验证,而不只是获取 URL;目录列表请求使用 POST。流程如下:GET /login → 解析 <meta name="csrftoken"> 的值,并保留响应 Cookie → POST /login/user,传入 username=<chain-code>、password=<password-or-empty>、csrftoken=<value>(有效的连锁代码会返回 302;无效代码会返回 200 并重新呈现表单)→ GET /file,并从该页面读取最新的 csrftoken → POST /file/json/dir,附带该令牌和 DataTables 分页参数以列出文件 → GET /file/d/<filename> 下载。

对 /file/json/dir 发起 GET 会返回 HTTP 200,响应内容为 {"aaData":[],"error":"Invalid request method used for this operation."}。这是一个空列表,而不是错误状态,因此发出 GET 请求的 Agent 会在毫无提示的情况下得出该连锁没有发布任何内容的结论。请参阅 references/chain-feeds.md,了解可用命令和各连锁代码。

第 2 步:解析连锁专属数据格式

每家连锁发布的 XML 架构略有不同。主要连锁包括:

连锁希伯来语名称平台备注
Shufersalשופרסל直连(prices.shufersal.co.il)最大的连锁,经营 Shufersal Deal、Sheli、Yesh 和 Express 等品牌;数据结构最完善。读取 Stores 数据流以获取当前门店数量
Rami Levyרמי לויCerberus(RamiLevi)以低价著称
YochananofיוחננוףCerberus侧重以色列中部地区
Victoryויקטורי不在 Cerberus 上(参见平台说明)与 Carrefour Israel 是不同的公司,并非 Carrefour 旗下品牌。该公司经营多个品牌(Victory、Victory Local、Victory City、Victory Plus、Victory Online),同一 SKU 在不同品牌下的定价可能不同,因此应按具体品牌和门店进行关键比较,而不是将“Victory”视为单一实体
Carrefour Israelקרפור ישראל直连(prices.carrefour.co.il)一个发布方并行覆盖多个品牌。其自身的 Stores 数据流会列出标有 בעיר 和 יינות ביתן 的门店,以及 Carrefour 门店,因此并非所有门店都使用 Carrefour 品牌
Osher Adאושר עדCerberus(用户名:osherad,无密码)折扣连锁,门店面积较大
Tiv Taamטיב טעםCerberus(TivTaam)销售非洁食商品,因此其商品组合与仅销售洁食商品的连锁不同

使用 scripts/parse_price_xml.py 将数据流解析为标准化的 JSON 格式。 关键字段:item_code、item_name、manufacturer、price、unit_price、quantity、unit_of_measure、is_weighted、update_date

**按重量销售商品的计算方式:**当 bIsWeighted=1 时,ItemPrice 表示每单位计量单位的价格,而不是货架上整包商品的价格;而且该单位不一定总是千克。读取 UnitOfMeasure 并据此进行标准化。在一份实时 Carrefour PriceFull 数据中,560 件按重量销售的商品里有 174 件声明的单位是 100 גרם,而不是千克单位,因此若将 ItemPrice 视为 NIS/kg,会使这些商品的价格高出一个数量级。实际数据中出现过的值包括 קילוגרם、ק"ג、1קילוגרם、100 גרם,甚至 100 ק"ג,空格使用也不一致。Quantity 可能为空或为小数。比较之前,必须将所有按重量销售的商品统一换算为相同单位,否则跨连锁排名会在毫无提示的情况下出错。

步骤 2.5:根据快照核对增量文件

Price 或 Promo 文件是增量文件,只包含发生变化的行。如果把它当作商品目录来解析,就会得到一份包含 200 件商品的“连锁目录”,但它实际上只是某天早上的编辑记录。

  • 从该门店最新的 PriceFull 开始,然后按文件名中的时间戳顺序应用 Price 增量文件。乱序应用会生成虚假的价格变动,这会严重影响步骤 5 的趋势追踪。
  • 增量文件中缺失的行表示未发生变化,而不是已删除。
  • 将某行视为有效价格前,先检查 ItemStatus;不要将已下架或非活跃 SKU 标为可购买。
  • 按门店核对。增量文件以门店为键,因此混合不同分店的数据会悄无声息地覆盖价格。
步骤 3:跨连锁价格比较

按以下方式匹配不同连锁的商品:

  • 条形码(最可靠,以色列标准条形码前缀为 729)
  • 商品名称 + 制造商(针对名称差异进行模糊匹配)
  • 商品代码(连锁特有,跨连锁匹配时可靠性较低)

部分主食类商品受法定价格管制(פיקוח מחירים),包括受管制的乳制品,因此其货架价格设有上限,且各连锁之间几乎相同。对于受管制商品,如果给出“换一家连锁购买即可省钱”的结果,就会夸大实际可节省的金额。我们无法获取当前权威的受管制商品清单(经济部页面无法通过机器获取),因此,在展示主食类商品的省钱信息前,请先核查相关管制令,而不要假定价差确实存在。

为指定商品生成比较表:

  • 计算:价格最低的连锁、平均价格、价格差(最高价减最低价)
  • 处理门店特定定价(同一连锁不同地点的价格可能不同)
步骤 4:优化购物清单

给定一份购物清单,找出最便宜的选择:

  • **单店:**整篮商品最便宜的商店
  • **多店:**在附近 2–3 家商店之间进行最优拆分(尽量降低总成本和出行成本)

将 PromoFull 数据源中的当前促销纳入考虑。促销字段的位置取决于方言,而这正是简单解析器会悄无声息地返回空结果的地方:

  • Cerberus 方言(Rami Levy 等):RewardType、MinQty、DiscountedPrice 和 DiscountRate 直接位于每个 <Promotion> 中,俱乐部 ID 则嵌套在 Clubs/ClubId 中,值为纯整数。
  • Shufersal / Carrefour 方言:<Promotion> 包含 PromotionID、PromotionDescription、 MinNoOfItemOffered、RedemptionLimit、PromotionDays 和一个扁平的 ClubID,而 RewardType、MinQty、MaxQty、DiscountRate 和 MinPurchaseAmount 则位于更深一层, 嵌套在 Groups/Group/PromotionItems/PromotionItem 中。

实际数据源中会出现 RewardType 值 1、2、3、7 和 9。常见的解读是 1 = 固定折后价,2 = N 件固定价,3 = 第 N 件折扣,但我们找不到任何代码映射的权威公开说明,因此应将这些解读视为惯例,并通过 PromotionDescription 加以确认,而非视为指定语义;切勿自动应用尚未确认的代码。

仅限俱乐部会员的促销需要按方言区别处理。 在 Cerberus 方言中,Clubs/ClubId 是整数, != 0 表示仅限俱乐部会员。在 Shufersal 方言中,ClubID 是一个以代码开头的字符串, 例如,开放促销的值为 0 - כלל הלקוחות。将该字符串与 0 比较总会得到不相等的结果,因此,将整数规则应用于 Shufersal 的解析器会把所有促销都误判为仅限俱乐部会员并过滤掉。解析 - 分隔符之前的前导整数,然后再进行判断。对仅限俱乐部会员的促销,不应应用于访客购物篮。

应用促销前,先筛选促销是否有效。 促销仅在其 PromotionStartDate/EndDate 时间范围内 且处于 PromotionStartHour/EndHour 时段内才有效,PromotionDays 还可能将促销限定在每周的特定日期。应用已过期或不在有效时间范围内的促销,会导致购物篮总价无法在收银台复现,这是此技能可能给出的最明显错误答案。

处理替代品:为类似商品推荐更便宜的替代选择。

计算每种方案的购物篮总成本。考虑用户偏好:犹太洁食要求、有机选项、品牌偏好。

步骤 5:追踪价格趋势

持续监控已追踪商品的价格:

  • 价格显著变化(上涨或下跌超过 10%)时发出提醒
  • 每周生成已追踪品类的价格趋势报告
  • 追踪各食品品类的通胀趋势
  • 与 CPI 食品分项数据进行比较
步骤 6:餐厅/餐饮食材成本分析

面向餐厅经营者:根据超市数据计算食材成本。

  • 输入:包含食材和用量的食谱
  • 输出:根据当前可获得的最低价格计算每份成本
  • 持续追踪食材成本趋势
  • 关键食材价格大幅上涨时发出提醒
  • 生成月度成本报告,辅助制定菜单定价决策

示例

示例 1:比较不同连锁超市的牛奶价格

用户说:“在哪里买 Tnuva 3% 牛奶(1 升)最便宜?” 操作:

  1. 查询相关连锁超市和门店的 PriceFull 数据源,查找商品(匹配条形码)
  2. 按连锁超市和门店汇总价格,以 (ChainId, SubChainId, StoreId, ItemCode) 为键
  3. 应用 PromoFull 中当前有效的促销,并按有效期和会员限制筛选
  4. 生成按价格排序的比较表

先回答价格管制问题。 3% 牛奶是受管制的基本商品,因此其货架价格有上限,不同连锁超市之间的价差几乎为零。坦诚的回答应该是“这件商品有价格上限,换一家连锁超市买也省不了多少钱”,然后指出购物清单中价差确实明显的非管制商品。不要针对受管制商品推荐“换一家买就能省钱”,也不要凭记忆报价格:要从实时数据源读取,因为价格每天都会变化。

示例 2:优化每周购物清单

用户说:“这是我这周的购物清单,帮我找出 Ramat Gan 附近最便宜的购买方案。” 操作:

  1. 解析购物清单(15 件商品)
  2. 查找 Ramat Gan 附近门店的各连锁超市价格
  3. 计算:单店购物(Rami Levy:285 NIS,Shufersal:310 NIS,Yochananof:295 NIS)
  4. 计算:最优两店组合(Rami Levy + Shufersal,含促销:262 NIS)
  5. 推荐 3 种替换商品,额外节省 18 NIS 结果:单店购物最优方案:Rami Levy,285 NIS。最优组合:Rami Levy(10 件商品,195 NIS)+ Shufersal(5 件商品,含促销,67 NIS)= 262 NIS。与单店购物相比,总共节省 23 NIS。
示例 3:追踪餐厅菜单的食材成本

用户说:“追踪我的沙克舒卡菜品的食材成本:西红柿、鸡蛋、洋葱、甜椒、香料。” 操作:

  1. 在价格数据源中找到匹配商品(新鲜西红柿、L 号鸡蛋、黄洋葱、甜椒、孜然、辣椒粉)
  2. 找出各连锁超市中每种食材的最低价格
  3. 计算每份成本(2 个鸡蛋、3 个西红柿、1 个洋葱、1 个甜椒、香料)
  4. 为这些食材设置每周价格监控
  5. 生成基准成本报告 结果:当前每份成本:8.40 NIS(连锁超市组合最低价)。鸡蛋占成本的 32%。已设置价格提醒;如果任何食材价格变化超过 10%,你会收到通知。

捆绑资源

参考资料
  • references/chain-feeds.md -- 按平台整理的各连锁超市数据源端点(Shufersal Direct、Carrefour Direct、Cerberus / PublishedPrices)。包含 XML 架构文档、更新时间表和已知的格式差异。在第 1–2 步访问连锁超市数据时查阅。
脚本
  • scripts/parse_price_xml.py -- 将 PriceFull 和 PromoFull 数据源解析为规范化 JSON。可自动检测文档中的 XML 方言,因此适用于任何连锁超市(--chain 仅作为来源标签)。输出连锁超市 / 子连锁 / 门店标识,解析两种方言中的促销,包括会员 ID 的字符串形式;通过魔数检测 gzip,并处理带 BOM 的 UTF-16。运行:python3 scripts/parse_price_xml.py --help

推荐的 MCP 服务

MCP提供的功能
以色列超市价格封装其覆盖的各连锁超市的价格透明法数据源。自动处理 Shufersal 直连、Carrefour publishprice 和 Cerberus FTP 传输。可用时,请用它替代手动 XML 步骤。
Shufersal MCP增加对 shufersal.co.il 的购物车自动化功能(搜索、加入购物车、食谱转购物车)。通过实际结账流程补充价格分析功能。

注意事项

  • 不要假设某个连锁品牌使用 Cerberus。Rami Levy、Yochananof、Osher Ad、Tiv Taam 和 Dor Alon 使用 Cerberus;Victory、Super-Pharm、Good Pharm、Bareket 和 Mega 不使用。Hazi Hinam 虽然登录 Cerberus 后看到的文件列表为空,但会在自家网站发布完整的文件表。同样,不要臆造 prices.<chain>.co.il 主机名,大多数连锁品牌都没有这样的主机。查看 references/chain-feeds.md 并重新探测后,再判断某个连锁品牌是否停止发布。
  • Cerberus 不是静态文件服务器,其目录列表使用 POST,而不是 GET。对 /file/json/dir 发送 GET 会返回 HTTP 200,响应内容为 {"aaData":[],"error":"Invalid request method used for this operation."};如果不检查 error 键,就会误以为该连锁品牌没有文件。目录列表的 POST 请求还需要一个从登录后的 /file 页面读取的 csrftoken,而不是登录前页面上的那个。没有会话时,请求 /file/d/<filename> 会返回 HTTP 302 和一个简短的重定向存根,而不是文件;因此,只有状态码为 2xx 且响应包含 gzip 负载时,才能将其视为数据。
  • 旧版“Nibit (Matrix)”主机 matrixcatalog.co.il 已完全无法解析(截至 2026-08-27 返回 NXDOMAIN),因此请求会在 DNS 阶段失败,而不是超时。其为 Victory 和 Mahsani A'Shuk 提供的后继服务是 laibcatalog.co.il。该域名可以解析,但我们的探测连接遭到拒绝;在依赖它之前,请先确认其状态。
  • 以色列的价格默认包含 VAT(18%),与未含税的美国价格不同。18% 的税率自 2025 年 1 月 1 日起生效(从 17% 上调);预算表决中,拟于 2026 年 1 月上调至 19% 的提案遭到否决。受训时间早于 2025 年的 Agent 可能会把 18%“纠正”回 17%,但不应这么做。根据训练数据中的假设,Agent 还可能在成本比较中重复计算 VAT,或完全忽略 VAT。
  • 以色列商品条形码使用 729 国家前缀,但一些进口商品仍保留原产国的条形码。如果同一商品在不同连锁品牌下使用不同格式的条形码,Agent 可能无法跨连锁品牌匹配商品。自有品牌商品通常使用以 2 开头的内部编码,根本无法进行跨品牌匹配。
  • club-id 字段在不同方言中的名称和类型各不相同:Cerberus feed 中是嵌套的整数 Clubs/ClubId;Shufersal/Carrefour 中则是扁平的字符串 ClubID,例如 0 - כלל הלקוחות。如果对 Shufersal 的字符串应用 Cerberus 的整数检查,就会把所有促销都标记为仅限会员,并悄无声息地全部丢弃;完全忽略该字段则会虚报节省金额。应解析开头的代码,再进行检查。
  • “Mega”和“Yeinot Bitan”并未完全重新品牌为 Carrefour。同一个发布方涵盖了三个品牌:Carrefour Israel 自己的 Stores feed 中,除了 Carrefour 门店,还列有以 בעיר 和 יינות ביתן 为品牌的门店。没有可用的独立 Mega feed 可作后备;独立的 prices.mega.co.il 主机返回 403,使用 Mega 账号登录 Cerberus 也会失败。“Victory”是完全不同的公司,并非 Carrefour 的品牌,Agent 经常会将两者混淆。Victory 旗下也经营多个品牌,同一 SKU 在不同品牌下的价格可能不同,因此比较时应以具体品牌和门店为依据,而不是把“Victory”视为一个整体。
  • 药房连锁品牌(Super-Pharm、Good Pharm)受相关法律约束,也会发布数据,但不通过 Cerberus:Super-Pharm 使用自己的门户 prices.super-pharm.co.il,Good Pharm 则通过 Bina Projects 发布数据。它们的 SKU 范围是药妆商品(洗漱用品、非处方药、婴儿食品),不包括新鲜农产品、乳制品或肉类,所以不要尝试比较 Super-Pharm 的牛奶价格。
  • 在 Cerberus 方言中,RewardType 及其同级的 MinQty / MaxQty / DiscountRate 位于 <Promotion> 元素上;而在 Shufersal/Carrefour 方言中,它们要深一层,位于 Groups/Group 内每个 PromotionItem 上。针对一种结构编写的解析器在另一种结构中什么也找不到,因而会报告促销数量为零。另请注意,Shufersal 中的 MinPurchaseAmount 与 MinPurchaseAmnt,以及 MinNoOfItemOffered 与 MinNoOfItemOfered 拼写确实不同。

参考链接

来源URL检查内容
Wikisource,《促进食品行业竞争法》(法规文本)https://he.wikisource.org/wiki/חוק_קידום_התחרות_בענף_המזון通俗易懂的摘要、立法历史、近期修订
经济部,价格公布法规https://www.gov.il/he/pages/cpfta_prices_regulations六种文件类型背后的文件规范、命名和编码规则。该页面受 Cloudflare 保护,因此请在浏览器中打开
Shufersal Direct 门户https://prices.shufersal.co.ilShufersal 的实时 PriceFull/PricesPromotions/Stores 数据源
Cerberus PublishedPrices 门户https://url.publishedprices.co.il/loginRami Levy、Yochananof、Tiv Taam、Osher Ad、Dor Alon 和其他 Cerberus 连锁店的实时数据源。Victory、Super-Pharm、Good Pharm、Bareket 和 Mega 不在此处,详见平台表
Carrefour Israel Direct 门户https://prices.carrefour.co.ilCarrefour / Mega / Yeinot Bitan 门店的实时数据源
OpenIsraeliSupermarkets,社区解析器https://github.com/OpenIsraeliSupermarkets社区使用的 Python 爬虫和解析器参考。当前活跃的库是 il-supermarket-scraper(PyPI),可处理 Cerberus CSRF 登录、连锁店代码查询、文件列表和解压缩。其爬虫类也是核对各连锁店当前发布平台的最佳参考
Super-Pharm 价格门户http://prices.super-pharm.co.ilSuper-Pharm 自有的数据源列表(不在 Cerberus 上)
Bina Projects 门户(Good Pharm)https://goodpharm.binaprojects.com/Main.aspxGood Pharm 和若干小型连锁店在此发布
Hazi Hinam 价格文件https://shop.hazi-hinam.co.il/PricesHazi Hinam 自有的文件列表
Israel Tax Authority,《Interpretation Directive 01/2025》https://www.gov.il/BlobFolder/dynamiccollectorresultitem/represent-info-051224-2/he/vat_represent-info-051224-2.pdf当前以色列增值税税率(自 2025 年 1 月 1 日起为 18%),包含历史税率变化

故障排除

错误:“XML feed download failed”

原因:对于 Shufersal,最可能的原因是签名 URL 已过期。Shufersal 门户的下载链接是 Azure Blob URL,其中包含一个约半小时后到期的 se= 参数,并且到期时间固定在整点边界,因此,之前捕获、缓存或从文档中复制的链接会失效。其他可能原因是该连锁店更换了平台(见平台表),或者该文件确实尚未发布。 解决方案:每次下载前立即重新列出文件,而不要重复使用已保存的 URL。对于其他平台,请重新探测列表端点,并确认该连锁店尚未迁移平台。数据源会在夜间刷新,因此当天较早时缺少 PriceFull 属于预期情况,并非错误。

错误:“Product not found in cross-chain comparison”

原因:不同连锁店的商品名称或条形码不一致。 解决方案:优先尝试按条形码匹配(最可靠)。如果条形码匹配失败,则使用模糊名称匹配,并结合制造商信息。一些连锁店对同一商品使用不同名称(例如,“חלב תנובה 3%”与“חלב 3% תנובה”)。

错误:“Price data outdated”

原因:使用了前一天的缓存数据,或者该连锁店尚未更新数据。 解决方案:检查 XML 数据源中的 UpdateDate 字段。大多数连锁店会在夜间更新。如果数据已超过 24 小时,请强制重新下载。促销数据源的更新可能晚于 PricesFull 更新。

错误:“Shopping list optimization slow”

原因:比较所有连锁店和所有门店中的所有商品,计算开销很大。 解决方案:将比较范围限制为可配置半径内(默认:5 km)设有门店的连锁店。根据用户实际购物的连锁店进行预筛选。使用缓存的价格数据,而不是每次优化都重新获取。

错误:“Cerberus 返回的文件列表为空”

原因(已于 2026-08-27 验证):使用 GET 请求获取列表。/file/json/dir 仅接受 POST 请求,对于 GET 请求会返回 HTTP 200,以及 {"aaData":[],"error":"Invalid request method used for this operation."}。另一个已验证的原因是 csrftoken 过期;获取列表需要使用登录后在 /file 页面上生成的令牌,而不是登录前的令牌。 已验证并非原因:异常的 User-Agent。本节中的所有探测都使用默认的 curl User-Agent,并成功完成登录、列表获取和下载,未遭拦截。 解决方案:遵循 references/chain-feeds.md 中的流程,并在将空的 aaData 视为“没有文件”之前,务必先读取 error 键。

错误:“Chain 登录 Cerberus 后没有文件”

原因(已于 2026-08-27 验证):该连锁店不通过 Cerberus 发布数据。Victory、SuperPharm、GoodPharm、Bareket 和 Mega 均无法登录(返回 200 并重新显示表单,而非 302);HaziHinam 可以通过身份验证,但列出的文件数为零,而 shop.hazi-hinam.co.il/Prices 上则提供了完整表格。 解决方案:在认定该连锁店已停止发布之前,先在 references/chain-feeds.md 中查找其实际平台。若要确信“连锁店 X 不发布数据”,必须先搜索连锁店 X 自己的门户网站。

评论

支持 Markdown