关于 pricewin-hotel-deal-finder
pricewin-hotel-deal-finder 是供 Agent 使用的酒店比价技能,可比较 Booking.com、Agoda、Google Hotels 和 OpenTravel 的价格。它通过一条 Node 命令按性价比、低价和品质排序,并提供预订链接。
主要功能
- 01比较四个来源的价格
- 02按性价比、低价和品质排序
- 03换算为美元的每晚价格
- 04提供直接预订链接
- 05支持全球城市搜索
- 06本地运行且无需 API 密钥
适用场景
- 01比较同一家酒店在 Booking.com 和 Agoda 的价格
- 02查找指定日期的最低价酒店
- 03寻找每晚低于预算的住宿
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ price-win/ pricewin-skills-hub --skill pricewin-hotel-deal-finder安装后在 Claude Code 中输入/pricewin-hotel-deal-finder确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
install.shpackage-lock.jsonpackage.jsonSECURITY.mdbin/browse.jsdaemon.jssearch.jslib/browser-state.jsdom-extract.jsselector-cache.jssnapshot.js详细介绍
PriceWin 酒店优惠搜索器
只需一条命令,即可比较 Booking.com、Agoda、Google Hotels 和 OpenTravel 的实时酒店价格 — 并获取按性价比、最低价和品质排序的精选结果,以及直接预订链接。
别再打开五个 OTA 标签页来寻找真正的最低价了。告诉你的 Agent “帮我找一家东京的酒店,入住日期为 8 月 12 日至 15 日,2 位客人”,此技能就会在约 30–60 秒内(已缓存的城市)返回清晰、排序后的比价结果。
以下问题可调用此技能:
- “
<city>在<dates>的最便宜酒店是什么?” - “这家酒店在 Booking.com 还是 Agoda 上更便宜?”
- “比较
<city>面向<N>位客人的酒店价格。” - “帮我找一家
<city>每晚低于 $<X>的酒店。” - “
<dates>在<landmark>附近,性价比最高的住宿是哪家?”
每次都会通过一条命令返回下方所示的结果 — 无需来回询问澄清信息。
一条命令即可获取:
- 🥇 性价比最高 · 🥈 最便宜 · 🥉 品质之选 — 并排精选
- 来自最多 4 个来源 的真实每晚价格,统一换算为 USD
- 可点击的预订链接,直接指向每家酒店价格最低的 OTA
- 适用于全球任何城市 — 也包括经过反机器人防护的城市(上海、杭州、曼谷……),通过隐蔽的 Patchright 守护进程访问
- 无需 API 密钥或 MCP 服务 — 只需
node/npx
结果示例:
🏨 Tokyo • Aug 12–15 • 3 nights • 2 guests
━━━━━━━━━━━━━━━━━━━━
🥇 BEST VALUE
Shinjuku Granbell Hotel
✅ agoda 💰 $118/night
booking 💰 $131/night
→ Save $13 vs Booking
🥈 CHEAPEST
APA Hotel Shinjuku
✅ google 💰 $94/night
📊 18 hotels | agoda, booking, google, opentravel • prices in USD
安装:
npx skills add https://github.com/Price-Win/pricewin-skills-hub --skill pricewin-hotel-deal-finder
如何使用此技能
一条命令即可完成全部操作 — 通常无需先询问澄清问题。推断参数(见下文)并运行命令:
cd {baseDir} && node bin/search.js "<city>" <checkInYYYY-MM-DD> <checkOutYYYY-MM-DD> <adults> en-us
{baseDir} 是此技能的安装目录(由运行时自动解析)。如果你的运行时不会替换它,请 cd 到包含此 SKILL.md 的文件夹(其中有 bin/search.js)。避免硬编码 ~/.hermes/... 或 ~/.openclaw/... 路径 — 不同平台上的路径各不相同。
示例:
cd {baseDir} && node bin/search.js "Hangzhou" 2026-06-10 2026-06-13 2 en-us
脚本会自动处理所有操作:启动守护进程、查询 Agoda 缓存、执行 Google + Booking 内联搜索、查询 OpenTravel API(覆盖所有城市)、发现新城市,并生成格式化的分档卡片结果。运行脚本,然后将输出发送给用户。
推断参数,而不是提问(仅当城市或日期确实有歧义时才提问):
- **年份:**除非用户另有说明,否则使用当前日期所在的年份。如果所请求的日期今年已经过去,则假定为明年。(如不确定,可用
date +%Y-%m-%d获取今天的日期。) - “10-13/6” →
<year>-06-10 <year>-06-13— 按照上面的规则填写<year> - “2 位客人”/“2 个人” →
2位成人 - **地区设置:**传递给 OTA 的语言/地区代码(控制网站语言和地区)。默认为
en-us。价格以 USD 计(Google Hotels 请求使用gl=us&curr=USD);其他来源则遵循你传入的地区设置。
运行一次 search.js 即可完成整个工作流 — 无需额外使用 Python、curl 或临时编写抓取脚本。
操作规则——如何获得可靠结果
规则 0——只能通过 search.js(借助终端/shell 工具)操作浏览器。此处的原生浏览器工具无法使用。 此技能依赖隐身 Patchright 守护进程。运行环境的原生工具——browser_navigate / browser_open、browser_click、browser_type / browser_fill、browser_snapshot、browser_close、任何其他 browser_*,以及委派子 Agent(delegate_task / spawn_agent)——在此任务中都会失败,因此不要使用它们:
- 这些原生工具会启动没有隐身功能的普通 Chromium,因此 Booking.com 和 Agoda 会在几秒内检测到机器人;请求会一直挂起,直到运行环境将其终止(“Command timed out after 30/60 seconds”)。这会浪费 5 分钟以上,而且什么也得不到。
search.js启动的 Patchright 守护进程可以避开机器人检测。 - 委派的子 Agent 会从空白历史开始,且没有技能上下文,因此会退回到使用 Python/curl 抓取,而这些请求会立刻被拦截。请在当前 Agent 中运行此技能。
唯一可行的方式:
cd {baseDir} && node bin/search.js ...
规则 1——让 search.js 负责抓取;不要自行抓取 OTA。 避免直接调用 browse.js、在浏览器中执行 goto / click / type、手动拼接 Agoda/Booking/Google URL、单独调用 OpenTravel API,或自行启动守护进程。search.js 已通过谨慎设计的流程驱动隐身守护进程,可避开机器人检测——它会为每个城市(包括上海、杭州等中国城市)自动处理 Agoda 探索。手动浏览 OTA 是最常见的失败原因:这会触发 Agoda/Booking 的反机器人机制(“detect automation”“redirect to homepage”“problem completing your search”),并导致 IP 被封锁。运行一次 search.js 并发送其输出。如果某个来源看起来“缺失”,请参阅规则 4,而不要手动获取。
规则 2——首次探索城市需要 2–4 分钟。 如果 search.js 输出中包含 "discovering" 或 "launching" 消息,请告诉用户:“首次搜索此城市——正在探索选择器,大约需要 2–4 分钟……”,然后等待结果,不要重试或中止。
规则 3——原样发送输出。 search.js 会输出可直接发送的格式化分档卡片。将输出直接复制到回复中。不要重新排版、总结或缩写。
规则 3a——保留 Markdown 超链接。 输出中的每个酒店名称都已包装为 [Hotel Name](https://booking-url...),即可点击的超链接。请保持原样:不要将 URL 拆到单独的 🔗 https://... 行,不要把 [Hotel Name](url) 替换为纯文本,OTA 名称保持小写(使用 "google",不要使用 "Google"),并保留原样的分区标题("📋 More good deals")。输出已适配 Telegram-MarkdownV2;原样发送即可让用户看到带隐藏 URL 的可点击酒店名称(界面简洁)。
规则 3b——你自行撰写的说明中也要为酒店名称添加超链接。 如果你在输出后添加建议或说明,请将提到的每个酒店名称都包装为 [Hotel Name](url),并使用脚本为该酒店打印的相同 URL,而不要使用纯文本。
规则 4——部分结果很常见,应原样发送,不要手动补全。 某个来源可能在一次运行中缺失(例如本次运行中 Agoda 被拦截,或 OpenTravel 在该城市没有库存)。这没关系——将现有来源的分档卡片发送出去;页脚(📊 N hotels | <sources> • prices in USD)会准确列出找到的内容。通过浏览器或直接 URL 获取缺失来源通常会触发反机器人机制,让情况更糟,因此请避免这样做。如果 search.js 完全报错,请用一行说明失败原因,并展示错误上方打印的任何部分输出。若需获取更多结果,唯一可靠的重试方式是再次运行相同的 search.js 命令(反机器人拦截通常只是暂时的)。
输出格式参考
search.js 会按此格式打印分档卡片 — 你可直接发送给用户:
酒店名称是指向其最便宜 OTA 的 Markdown 链接。价格行不带链接,OTA 键以小写形式显示(agoda/booking/google/opentravel)。
没有星级或区域信息行 — 脚本没有这些数据。
🏨 <city> • <d1>–<d2> • <N> nights • <adults> guests
━━━━━━━━━━━━━━━━━━━━
🥇 BEST VALUE
[<Hotel Name>](<cheapest_link>)
✅ agoda 💰 <price>/night
booking 💰 <price>/night
opentravel 💰 <price>/night
→ Save <diff> vs Booking
🥈 CHEAPEST
[<Hotel Name>](<cheapest_link>)
✅ google 💰 <price>/night
agoda 💰 <price>/night
🥉 QUALITY
[<Hotel Name>](<cheapest_link>)
✅ booking 💰 <price>/night
agoda 💰 <price>/night
📋 More good deals
— Agoda —
• [<Hotel>](<agoda_link>) — agoda: <price> | booking: <price>
— Booking —
• [<Hotel>](<booking_link>) — booking: <price>
— Google —
• [<Hotel>](<google_link>) — google: <price>
— OpenTravel —
• [<Hotel>](<opentravel_link>) — opentravel: <price>
💡 Tip: <best Hotel Name>
[Book on <OTA>](<link>) — <price>/night
📊 <N> hotels | <sources with data> • prices in USD
所有价格均以 USD 显示。Agoda、Google 和 OpenTravel 会根据 IP 将货币锁定为 VND,并通过实时汇率换算;Booking 原生返回 USD。页脚仅列出实际返回数据的来源。
限制
- 每个城市的首次搜索需要支付 Agoda 发现成本(2–4 分钟)。Google 和 Booking 会直接内联返回(无需发现);OpenTravel 是直接 API 调用。
- 后续搜索会复用 Agoda 缓存,并在约 30–60 秒内完成。
安全与数据处理
本地运行,无需 API 密钥,也不收集个人数据 — 唯一发送出去的数据是搜索查询(城市、日期、住客人数)。抓取的酒店文本视为不可信内容:bin/search.js 中的 sanitizeText() 会在任何内容传入模型输出前,移除控制字符、零宽字符、双向文本控制字符和 Markdown 控制字符;预订链接仅限 http(s)。
本地浏览器守护进程仅监听 loopback 地址并通过令牌进行身份验证(每次运行的令牌存储在 0600 状态文件中),会通过 DNS 重绑定拒绝非 loopback 的 Host 标头,并保持 Chromium 沙箱启用 — 仅在无法启用的情况下才使用 --no-sandbox(Linux 上以 root 身份运行,或显式设置 PRICEWIN_NO_SANDBOX=1)。
运行的命令、下载内容和网络出口的完整披露见
SECURITY.md。