
Ethan Collins
Pattern Recognition Specialist

酒店价格监控数据对AI旅行代理而言只有在每个价格具有可比性、时效性并可追溯到其来源时才具有价值。显示的每晚价格可能省略税费、依赖入住人数、需要会员资格,或与旁边的优惠有不同的取消政策。因此,正确的架构应从官方酒店和旅行API开始,将每个优惠转换为通用模式,计算透明的总住宿费用,并记录采集时间戳和条件。授权浏览器采集可以填补文档缺口,但CAPTCHA恢复应保持为受控例外,而非主要获取方式。本指南构建了一个实用的监控流程,用于价格警报、灵活日期推荐、平价分析和行程规划,同时保留同意、来源条款和人工批准的预订。
在代理了解客人获得的服务和适用的约束条件之前,价格并不具有可比性。至少需捕获:
from dataclasses import dataclass, field
from datetime import datetime, timezone
@dataclass
class HotelOffer:
property_id: str
property_name: str
source: str
check_in: str
check_out: str
adults: int
children: int
room_type: str
meal_plan: str | None
refundable: bool | None
cancellation_deadline: str | None
currency: str
nightly_base: float
taxes: float
fees: float
total_price: float
rate_key: str | None
collected_at: str = field(
default_factory=lambda: datetime.now(timezone.utc).isoformat()
)
总价格应代表请求的住宿和入住人数。如果税费或强制费用未知,应将该优惠标记为不完整,而非将其作为最便宜选项进行排名。
CapSolver网页抓取博客包含通用采集模式,CapSolver网页抓取常见问题涵盖常见操作问题。
官方API提供明确的模式、认证和商业条款。Sabre获取酒店价格信息API描述了从多个供应源获取实时物业价格信息。其响应可能包括平均每晚价格、货币、税前和税后金额、费用、房间详情、餐饮计划、担保要求、取消条款和价格键。
Google的酒店价格文档定义了酒店列表、可用性、价格和库存、交易、价格规则、查询和日期/时间格式的合作伙伴资源。当前的Amadeus企业API门户为企业客户提供酒店相关API的访问权限。
| 数据源 | 最佳用途 | 优势 | 约束条件 |
|---|---|---|---|
| 酒店或连锁API | 第三方可用性和直接价格 | 清晰的所有权和当前库存 | 仅限一个供应商 |
| GDS或旅行API | 多供应商价格搜索 | 结构化优惠和预订键 | 需要合同和认证 |
| 合作伙伴数据流 | 大量库存和价格更新 | 高效的批量处理 | 合作伙伴批准和数据流规则 |
| 授权公共页面 | 验证或填补空白 | 反映面向客户显示 | 布局变化和流量验证 |
不要将合作伙伴数据流视为通用公共端点。遵循提供商协议、缓存策略、显示规则和预订要求。
不同来源返回不同的结构。将每个来源置于一个小适配器后,返回相同的HotelOffer模型。
import requests
from decimal import Decimal
class HotelRateAdapter:
def __init__(self, base_url: str, token: str):
self.base_url = base_url.rstrip("/")
self.token = token
def search(
self,
property_id: str,
check_in: str,
check_out: str,
adults: int = 2,
currency: str = "USD",
) -> list[HotelOffer]:
response = requests.post(
f"{self.base_url}/hotel-rates/search",
headers={
"Authorization": f"Bearer {self.token}",
"Accept": "application/json",
},
json={
"propertyId": property_id,
"checkIn": check_in,
"checkOut": check_out,
"adults": adults,
"currency": currency,
},
timeout=30,
)
response.raise_for_status()
return [self._normalize(item) for item in response.json()["offers"]]
def _normalize(self, raw: dict) -> HotelOffer:
base = Decimal(str(raw["price"]["base"]))
taxes = Decimal(str(raw["price"].get("taxes", 0)))
fees = Decimal(str(raw["price"].get("fees", 0)))
return HotelOffer(
property_id=raw["propertyId"],
property_name=raw["propertyName"],
source=raw["source"],
check_in=raw["checkIn"],
check_out=raw["checkOut"],
adults=raw["occupancy"]["adults"],
children=raw["occupancy"].get("children", 0),
room_type=raw["room"]["name"],
meal_plan=raw.get("mealPlan"),
refundable=raw.get("refundable"),
cancellation_deadline=raw.get("cancellationDeadline"),
currency=raw["price"]["currency"],
nightly_base=float(base),
taxes=float(taxes),
fees=float(fees),
total_price=float(base + taxes + fees),
rate_key=raw.get("rateKey"),
)
上述端点和字段映射代表适配器边界;用您批准的提供商的精确合同替换它们。在生产代码中,永远不要虚构提供商字段。
价格比较错误通常来自不匹配的条件,而非算术问题。仅在共享相同物业、入住日期、入住人数、房间类别和价格限制时对优惠进行分组。
from dataclasses import asdict
def comparison_key(offer: HotelOffer) -> tuple:
return (
offer.property_id,
offer.check_in,
offer.check_out,
offer.adults,
offer.children,
offer.room_type.strip().lower(),
(offer.meal_plan or "unknown").strip().lower(),
offer.refundable,
)
def comparable_snapshot(offers: list[HotelOffer]) -> list[dict]:
return sorted(
[asdict(o) for o in offers],
key=lambda item: (
item["total_price"],
item["source"],
),
)
使用带时间戳的来源转换货币并保留原始金额。在没有显式调整或用户偏好时,不要比较可退款早餐价格与不可退款的仅房间价格。
CapSolver Python抓取指南在构建适配器时很有用,CapSolver术语表可帮助跨团队标准化术语。
酒店价格因物业、日期、库存压力和预订窗口而变化。使用基于策略的计划,而非以相同频率轮询每个物业。
from datetime import date
def monitoring_interval_days(check_in: date, today: date) -> int:
days_out = (check_in - today).days
if days_out <= 3:
return 1
if days_out <= 14:
return 2
if days_out <= 60:
return 4
return 7
生产调度器还应考虑提供商限制、物业优先级、近期价格波动和用户警报设置。抖动作业启动时间以避免请求洪峰。
避免因微小货币或四舍五入差异发出警报。比较总费用和重大政策变化。
from decimal import Decimal
def detect_offer_change(previous: HotelOffer, current: HotelOffer) -> dict:
old_total = Decimal(str(previous.total_price))
new_total = Decimal(str(current.total_price))
amount_change = new_total - old_total
pct_change = (
(amount_change / old_total * 100) if old_total else Decimal("0")
)
policy_changed = any([
previous.refundable != current.refundable,
previous.cancellation_deadline != current.cancellation_deadline,
previous.meal_plan != current.meal_plan,
])
return {
"amount_change": float(amount_change),
"percent_change": round(float(pct_change), 2),
"policy_changed": policy_changed,
"alert": abs(pct_change) >= Decimal("5") or policy_changed,
}
阈值应反映应用程序。企业差旅计划可能关注小的政策变化,而消费者警报可能强调更大的总费用减少。
一些批准的工作流需要验证公共显示价格或收集合同API中不可用的字段。仅在网站条款和您的协议允许时使用浏览器备用方案。
用户提供的CapSolver代理文档将浏览器恢复映射到capsolver-core中的detect()和solve_on_page():
import os
from capsolver_core import Capsolver
cap = Capsolver(
api_key=os.environ["CAPSOLVER_API_KEY"],
default_timeout=180,
)
async def recover_rate_check(page) -> dict:
challenge = await cap.detect(page)
if not challenge:
return {"handled": False, "reason": "No supported challenge detected"}
result = await cap.solve_on_page(page)
return {"handled": True, "result": result}
保持相同的授权浏览器上下文,保留保守的请求速率,并在一次限定恢复尝试后停止。CapSolver CAPTCHA解决常见问题解释了通用任务生命周期,CapSolver故障排除常见问题涵盖了常见故障条件。
附加代码:在CapSolver仪表板使用代码 WEBS,每次充值可额外获得5%的奖金。
AI旅行代理应接收简洁、有证据支持的快照,而非原始提供商负载。
def build_agent_snapshot(offers: list[HotelOffer]) -> dict:
complete = [
offer for offer in offers
if offer.total_price > 0 and offer.currency and offer.room_type
]
complete.sort(key=lambda offer: offer.total_price)
return {
"query": {
"property_id": complete[0].property_id if complete else None,
"check_in": complete[0].check_in if complete else None,
"check_out": complete[0].check_out if complete else None,
},
"best_flexible_offer": asdict(complete[0]) if complete else None,
"alternatives": [asdict(o) for o in complete[1:6]],
"warnings": [
"价格可能在预订前发生变化。",
"在结账时验证总费用、可用性和取消条款。",
],
}
提示代理解释价格与灵活性之间的权衡。除非提供商的预订或价格检查端点已确认,否则不应声称房间已预订或价格已保证。
监控是只读的。预订会改变库存、创建财务义务,并通常需要个人数据。将这些功能保留在独立服务中,并在调用任何预订端点前要求明确确认。
| 阶段 | 自动化级别 | 必需控制 |
|---|---|---|
| 价格采集 | 自动化 | 批准的来源和速率限制 |
| 标准化 | 自动化 | 模式验证和来源 |
| 警报生成 | 自动化 | 用户定义的阈值 |
| 推荐 | 协助 | 透明的比较标准 |
| 价格重新检查 | 自动化在购买前 | 新的提供商确认 |
| 预订和支付 | 人工确认 | 认证和明确同意 |
此边界可防止AI代理将过时的监控观察转化为意外购买。
跟踪物业匹配置信度、来源延迟、缺失税费、货币转换时间、重复价格键、解析器版本和采集错误。在许可时保留原始提供商响应或完整性哈希。当物业无法在不同来源中自信匹配时,将其路由至审查,而非仅通过名称合并记录。
有用的指标包括每来源的成功观察数、不完整价格率、中位采集延迟、实质性价格变化率、挑战遭遇率和人工审查量。这些指标可在影响推荐前揭示数据质量问题。
仅通过授权的API、数据流、网站和账户使用酒店价格监控。遵循合作伙伴合同、网站条款、缓存限制、区域消费者定价规则和隐私要求。未经明确同意,不得收集私人预订数据或忠诚账户信息。尽量减少浏览器流量,并在可用时优先使用官方结构化接口。
可靠的酒店价格监控数据需要的不仅仅是从页面上收集一个数字。AI旅行代理需要标准化的住宿条件、全包总费用、政策细节、时间戳和来源来源。官方酒店和GDS API应作为基础;授权浏览器检查可在受控恢复层中提供有限的空白覆盖,当支持的挑战中断会话时,CapSolver可作为受控恢复层。
构建第一个经过批准的工作流程,使用CapSolver,然后添加特定于供应商的适配器、价格变动阈值,并在任何预订操作前进行强制性重新检查。
至少需要存储物业ID、入住日期、入住人数、房型、餐饮计划、可退款性、取消截止日期、货币、税费、费用、总价格、来源和采集时间戳。
首先使用官方API和合作伙伴数据源。当结构化访问无法提供所需字段时,浏览器采集应仅限于允许的公共页面或经批准的QA和验证任务。
根据预订窗口、价格波动性、供应商限制和警报紧急程度制定策略。近期入住应更频繁检查,远期入住则较少检查。
不能。在预订前通过供应商立即重新检查价格和可用性,并在创建预订或支付义务前要求用户明确确认。
CapSolver是受控恢复层,用于授权浏览器会话中的支持挑战。它不会取代供应商访问权限、费率限制、API或预订确认。