mcpField
S
sutochno

sutochno

github.com/borski生产力78040 次安装2 天前更新
代码仓库

关于 sutochno

sutochno 是用于搜索 Sutochno.ru 短租房源的命令行技能,适合寻找格鲁吉亚及其他 CIS 目的地住宿的旅客。它抓取城市页面并提供可筛选、排序的结果和链接,但不负责预订。

主要功能

  1. 01按城市子域名搜索房源
  2. 02按评分和每晚价格筛选
  3. 03对结果排序并去重
  4. 04以 JSON 或表格返回房源链接

适用场景

  1. 01查找第比利斯或巴统住宿
  2. 02按卢布每晚价格筛选住宿
  3. 03预订前比较房东直租房源

安装

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

$npx skills add https://github.com/borski/travel-hacking-toolkit --skill sutochno

安装后在 Claude Code 中输入/sutochno确认已加载。

包含的文件

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

Dockerfile
scripts/
entrypoint.sh
search_sutochno.py
tests/
test_search_sutochno.py

详细介绍

Sutochno 搜索

搜索 Sutochno.ru(СУТОЧНО.РУ)——一个俄罗斯短租市场平台,用户可以直接向房东预订公寓、房间和房屋,并以卢布付款,通常使用 Mir 卡或银行转账。对于预订格鲁吉亚 / 独联体住宿的俄语旅客来说,这是很自然的选择,因为 Airbnb 和 Booking 已撤出,或不接受俄罗斯银行卡。它可与 Airbnb MCP 和 vrbo 技能搭配使用:前者覆盖西方房源,Sutochno 则能找到这些平台遗漏的卢布定价、房东直租房源。

Sutochno 不受 Akamai 保护。 与需要应对 Akamai 反机器人墙、必须以有头模式运行的 vrbo 技能不同,Sutochno 的服务端渲染城市页面在无头模式下也能正常加载——无需绕过机器人检测机制。此技能仍基于工具包标准的 patchright-docker 镜像构建(与其他浏览器技能使用相同镜像),但仅用于提供捆绑的 chromium 和 OS 依赖;它不需要 Patchright 的隐身功能。Patchright 是 Playwright 的直接替代分支,因此浏览器 API 相同。默认使用无头模式;--headed 可用于调试。

JSON API 需要身份验证——因此我们改为抓取页面。 Sutochno 的 /api/* 端点(例如 /api/geo/suggest)如果没有 SPA 在客户端计算的应用令牌,就会返回 403 Application authentication failed。因此,此技能不会调用 API,而是抓取服务端渲染的城市页面,其中房源卡片已包含在 HTML 中。

城市搜索结果位于子域名上。 每个城市都有自己的主机名: https://tbilisi.sutochno.ru/、https://batumi.sutochno.ru/、 https://kutaisi.sutochno.ru/ 等。国家目录 https://sutochno.ru/georgia 会列出格鲁吉亚支持的城市,并链接至 https://{city}.sutochno.ru/<listingId> 房源卡片。传入城市作为 子域名关键词(--city tbilisi),或传入完整 URL(--url)。

无需登录。 Sutochno 的搜索结果公开可见;此技能会查找出租房源并返回链接,不会登录或完成预订。

前置条件

pip install patchright && patchright install chromium

或使用 Docker(无需本地安装):

docker build -t sutochno skills/sutochno/

适用场景

  • 俄语旅客(或与俄语同伴同行的旅客)预订通过 Mir 卡或银行转账以卢布支付的住宿
  • 预订格鲁吉亚 / 独联体住宿(第比利斯、巴统、库塔伊西等),而 Airbnb / Booking 已撤出或不接受俄罗斯银行卡
  • 预订多晚住宿前,将房东直租的卢布计价房源与 Airbnb / VRBO 进行交叉对比

不适用场景

  • 完成预订。 此技能只查找出租房源并返回链接。不要尝试完成购买或联系房东。
  • 独联体以外的目的地。 对于西方目的地,Airbnb(MCP)、vrbo 技能和 Booking 的房源更丰富、银行卡支持也更完善——请使用这些平台。
  • 酒店 / 品牌连锁酒店。 请使用 compare-hotels / serpapi / liteapi / 门户技能。

用法

# Tbilisi, human-readable table (headless by default)
python3 skills/sutochno/scripts/search_sutochno.py --city tbilisi

# Batumi, JSON, only 9.0+ rated, under 8000 rubles/night, top 15
python3 skills/sutochno/scripts/search_sutochno.py --city batumi \
  --min-rating 9.0 --max-price 8000 --limit 15 --json

# Explicit full URL (e.g. a city page with query filters already applied)
python3 skills/sutochno/scripts/search_sutochno.py \
  --url "https://kutaisi.sutochno.ru/" --json

# Docker
docker run --rm sutochno --city tbilisi --json
参数
标志默认值说明
--citycity/url 必填其一城市子域名关键词,例如 tbilisi、batumi。解析为 https://{city}.sutochno.ru/。
--urlcity/url 必填其一完整城市 URL——如果要传入已包含查询筛选条件的页面,请使用此参数代替 --city。
--min-rating0客户端筛选,评分范围为 0–10(例如 9.0)。保留没有评分的房源。
--max-price0客户端筛选,每晚卢布价格上限。保留没有价格的房源。
--limit20返回的房源数量上限(排序后)。
--headedoff以有头模式运行浏览器(仅用于调试——Sutochno 没有机器人墙,因此默认使用无头模式)。
--jsonoff将 JSON 输出到 stdout(用于编排)。

选择器(抓取契约)

在城市页面上,每个房源卡片包含:

字段选择器原始格式提取方式
名称 + 链接.card-content__object-type(一个 <a>)文本 + href → https://{city}.sutochno.ru/<id>(或 /hotels/<id>)名称文本;id = href 末尾的数字
价格.card-prices__price"4 890 ₽ за сутки"取 ₽ 之前的子字符串,去掉所有非数字字符 → 4890
评分 + 评论数.card-prices__rating"10 отзывов 9,8 (10) …"评分 = 首个 /\d{1,2},\d/(逗号 → 点);评论数 = /(\d+)\s*отзыв/
地址.card-content__address"Тбилиси, Старый город"原样提取

卡片包装元素是名称节点最近的、同时包含 .card-prices 元素的祖先——名称和价格是同级元素,而非嵌套关系。因此,提取器会从名称链接开始向上遍历,直到 el.querySelector('.card-prices') 为真,然后从该包装元素内读取价格和评分。

价格注意事项:价格字符串中的千位分隔符是混合宽度/不换行空格,因此简单的 \d+ 正则会截掉首位数字(对 4 890 返回 890)。可靠的方法是按 ₽ 分割,再去掉所有非数字字符——这正是 parse_price 的处理方式。

图片是延迟加载的占位图(首次渲染时为 lzy-img.gif),因此抓取器不依赖照片。

输出

使用 --json 时的 JSON 结构:

{
  "source": "sutochno",
  "searchUrl": "https://tbilisi.sutochno.ru/",
  "query": { "city": "tbilisi", "url": null, "min_rating": 9.0, "max_price": 8000 },
  "count": 12,
  "listings": [
    {
      "id": "1234567",
      "name": "Уютная студия в центре",
      "area": "Тбилиси, Старый город",
      "rub_per_night": 4890,
      "rating": 9.8,
      "reviews": 10,
      "url": "https://tbilisi.sutochno.ru/1234567"
    }
  ]
}

房源按 id 去重,并按评分降序、再按价格升序排序(没有评分/价格的条目排在最后)。rub_per_night 是以卢布计价的每晚起始价格——请打开房源 URL 确认总费用(清洁费、押金以及房东收取的其他费用可能未计入搜索结果页面的价格)。

测试

纯逻辑(城市 URL 构建、卢布价格解析、评分/评论数解析、房源 ID 提取、标准化、去重/筛选/排序)由标准库 unittest 测试覆盖——无需浏览器、网络或 Patchright(patchright 采用延迟导入):

python3 -m unittest discover -s skills/sutochno/tests -v   # or: python3 -m pytest skills/sutochno/tests

浏览器驱动的流程(页面导航、DOM 提取)无法离线进行单元测试——请通过真实的城市搜索进行验证(参见上文“用法”)。

已知脆弱点

  • **DOM 选择器可能发生变化。**Sutochno 可能会修改 card-content__*/card-prices__* 类名。如果在已知有房源的城市进行实时搜索时返回 0 张卡片,请重新检查城市页面,并更新 EXTRACT_JS 和上方的选择器表(提交一个 P2 任务)。
  • **API 仍受身份验证限制。**不要尝试重新使用 /api/*——它需要 SPA 计算得出的应用令牌;没有该令牌时会返回 403 Application authentication failed。服务端渲染页面才是受支持的接口。

评论

支持 Markdown