关于 israeli-grocery-price-intelligence
israeli-grocery-price-intelligence 是利用以色列零售连锁公开数据源或现有 MCP 服务分析食品杂货价格的技能。它指导数据源访问、XML 解析、价格归一化和跨连锁比较;无需自动化时也会推荐现有比价应用。
主要功能
- 01选择消费应用或原始数据源
- 02访问各连锁专属价格数据源
- 03解析并归一化 XML 价格
- 04合并完整快照与增量文件
- 05跨连锁比较商品
适用场景
- 01自动比较购物清单总价
- 02构建自定义购物清单优化器
- 03跟踪价格变化趋势
- 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.mdevidence.jsonmetadata.jsonoptimization-log.jsonSKILL_HE.mdreferences/chain-feeds.mddomain-checklist.mdscripts/parse_price_xml.py详细介绍
以色列杂货价格情报
说明
非开发者最快上手方式:现成的比价应用
如果用户只是想知道某件商品或一篮子商品在哪里最便宜(而不是要构建自动化工作流),推荐他们使用已经能解析这些数据源的消费者比价服务,无需编写代码:
- CHP(https://chp.co.il)是以色列使用最广泛的杂货比价网站,可跨附近门店比较整篮商品。
- Pricez(https://www.pricez.co.il)和 Savy(https://www.savy.co.il)是其他消费者比价应用。
- 经济部官方认可的比价应用列表(https://www.gov.il/he/pages/cpfta_apps)是根据价格透明法审查通过的服务权威目录。
当用户需要自动化、自定义购物清单优化器、趋势跟踪或消费者应用不支持的餐厅成本分析时,再使用下方的原始数据源 / 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 - 3 段格式:
-
每家 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 Direct | https://prices.shufersal.co.il | Shufersal | 公开列表页;下载链接是会过期的签名 URL(见下文) |
| Carrefour Israel Direct | https://prices.carrefour.co.il | Carrefour Israel(Carrefour / Mega / Yeinot Bitan 品牌门店) | 公开;文件列表内嵌在页面中,下载地址为 /<yyyyMMdd>/<filename> |
| Cerberus (PublishedPrices) | https://url.publishedprices.co.il/login | Rami Levy、Yochananof、Tiv Taam、Osher Ad、Dor Alon、Keshet Taamim、Fresh Market / Super Dosh、Cofix (SuperCofixApp) | 会话登录 + CSRF(见下文) |
| Super-Pharm 自有门户 | http://prices.super-pharm.co.il | Super-Pharm | 公开列表页 |
| Bina Projects | https://goodpharm.binaprojects.com/Main.aspx | Good Pharm,以及几家小型连锁(King Store、Shuk Ahir、Zol VeBegadol、Bareket) | 各连锁子域名上的公开列表页 |
| 连锁自有网站 | https://shop.hazi-hinam.co.il/Prices | Hazi 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 升)最便宜?” 操作:
- 查询相关连锁超市和门店的
PriceFull数据源,查找商品(匹配条形码) - 按连锁超市和门店汇总价格,以
(ChainId, SubChainId, StoreId, ItemCode)为键 - 应用
PromoFull中当前有效的促销,并按有效期和会员限制筛选 - 生成按价格排序的比较表
先回答价格管制问题。 3% 牛奶是受管制的基本商品,因此其货架价格有上限,不同连锁超市之间的价差几乎为零。坦诚的回答应该是“这件商品有价格上限,换一家连锁超市买也省不了多少钱”,然后指出购物清单中价差确实明显的非管制商品。不要针对受管制商品推荐“换一家买就能省钱”,也不要凭记忆报价格:要从实时数据源读取,因为价格每天都会变化。
示例 2:优化每周购物清单
用户说:“这是我这周的购物清单,帮我找出 Ramat Gan 附近最便宜的购买方案。” 操作:
- 解析购物清单(15 件商品)
- 查找 Ramat Gan 附近门店的各连锁超市价格
- 计算:单店购物(Rami Levy:285 NIS,Shufersal:310 NIS,Yochananof:295 NIS)
- 计算:最优两店组合(Rami Levy + Shufersal,含促销:262 NIS)
- 推荐 3 种替换商品,额外节省 18 NIS 结果:单店购物最优方案:Rami Levy,285 NIS。最优组合:Rami Levy(10 件商品,195 NIS)+ Shufersal(5 件商品,含促销,67 NIS)= 262 NIS。与单店购物相比,总共节省 23 NIS。
示例 3:追踪餐厅菜单的食材成本
用户说:“追踪我的沙克舒卡菜品的食材成本:西红柿、鸡蛋、洋葱、甜椒、香料。” 操作:
- 在价格数据源中找到匹配商品(新鲜西红柿、L 号鸡蛋、黄洋葱、甜椒、孜然、辣椒粉)
- 找出各连锁超市中每种食材的最低价格
- 计算每份成本(2 个鸡蛋、3 个西红柿、1 个洋葱、1 个甜椒、香料)
- 为这些食材设置每周价格监控
- 生成基准成本报告 结果:当前每份成本: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 自己的
Storesfeed 中,除了 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.il | Shufersal 的实时 PriceFull/PricesPromotions/Stores 数据源 |
| Cerberus PublishedPrices 门户 | https://url.publishedprices.co.il/login | Rami Levy、Yochananof、Tiv Taam、Osher Ad、Dor Alon 和其他 Cerberus 连锁店的实时数据源。Victory、Super-Pharm、Good Pharm、Bareket 和 Mega 不在此处,详见平台表 |
| Carrefour Israel Direct 门户 | https://prices.carrefour.co.il | Carrefour / Mega / Yeinot Bitan 门店的实时数据源 |
| OpenIsraeliSupermarkets,社区解析器 | https://github.com/OpenIsraeliSupermarkets | 社区使用的 Python 爬虫和解析器参考。当前活跃的库是 il-supermarket-scraper(PyPI),可处理 Cerberus CSRF 登录、连锁店代码查询、文件列表和解压缩。其爬虫类也是核对各连锁店当前发布平台的最佳参考 |
| Super-Pharm 价格门户 | http://prices.super-pharm.co.il | Super-Pharm 自有的数据源列表(不在 Cerberus 上) |
| Bina Projects 门户(Good Pharm) | https://goodpharm.binaprojects.com/Main.aspx | Good Pharm 和若干小型连锁店在此发布 |
| Hazi Hinam 价格文件 | https://shop.hazi-hinam.co.il/Prices | Hazi 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 自己的门户网站。