
Emma Foster
Machine Learning Engineer

Data pemantauan harga hotel hanya bernilai bagi agen perjalanan AI ketika setiap tarif dapat dibandingkan, terkini, dan dapat dilacak ke sumbernya. Harga malam yang ditampilkan bisa menghilangkan pajak, bergantung pada jumlah tamu, memerlukan keanggotaan, atau menggunakan kebijakan pembatalan yang berbeda dari tawaran di sampingnya. Arsitektur yang benar mulai dari API hotel dan perjalanan resmi, mengonversi setiap tawaran ke dalam skema umum, menghitung total masa inap yang transparan, dan mencatat waktu pengumpulan dan kondisi. Pengumpulan browser yang diizinkan dapat mengisi celah yang terdokumentasi, tetapi pemulihan CAPTCHA harus tetap menjadi pengecualian yang terkendali, bukan metode utama. Panduan ini membangun alur kerja pemantauan yang praktis untuk pemberitahuan tarif, rekomendasi tanggal fleksibel, analisis kesetaraan, dan perencanaan itinerari sambil mempertahankan persetujuan, ketentuan sumber, dan persetujuan manusia untuk pemesanan.
Sebuah tarif tidak dapat dibandingkan sampai agen mengetahui apa yang diterima tamu dan batasan yang berlaku. Paling tidak, tangkap:
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()
)
Harga total harus mewakili masa inap dan jumlah tamu yang diminta. Jika pajak atau biaya wajib tidak diketahui, label tawaran sebagai tidak lengkap daripada mengurutkannya sebagai opsi termurah.
Blog web-scraping CapSolver berisi pola pengumpulan umum, dan FAQ web-scraping CapSolver menutupi pertanyaan operasional umum.
API resmi menyediakan skema, otentikasi, dan ketentuan komersial yang jelas. Sabre Get Hotel Rate Info API menggambarkan pengambilan tarif properti langsung dari berbagai sumber pasokan. Responsnya dapat mencakup rata-rata tarif per malam, mata uang, jumlah sebelum dan sesudah pajak, biaya, detail kamar, rencana makan, persyaratan jaminan, ketentuan pembatalan, dan kunci tarif.
Google's Hotel Prices documentation mendefinisikan sumber mitra untuk daftar hotel, ketersediaan, tarif dan inventaris, transaksi, aturan tarif, pertanyaan, dan format tanggal/waktu. Portal Amadeus Enterprise API saat ini menyediakan akses ke API terkait hotel untuk pelanggan perusahaan yang disetujui.
| Sumber data | Penggunaan terbaik | Kekuatan | Keterbatasan |
|---|---|---|---|
| API hotel atau rantai | Ketersediaan pihak pertama dan tarif langsung | Kepemilikan jelas dan inventaris terkini | Terbatas pada satu pemasok |
| GDS atau API perjalanan | Pencarian tarif multi-pemasok | Tawaran yang terstruktur dan kunci pemesanan | Kontrak dan otentikasi diperlukan |
| Feed mitra | Inventaris besar dan pembaruan harga | Pemrosesan batch yang efisien | Persetujuan mitra dan aturan feed |
| Halaman publik yang diizinkan | Validasi atau penutupan celah | Mencerminkan tampilan yang dilihat tamu | Perubahan tata letak dan validasi lalu lintas |
Jangan memperlakukan feed mitra sebagai endpoint publik umum. Ikuti perjanjian penyedia, kebijakan cache, aturan tampilan, dan persyaratan pemesanan.
Sumber berbeda mengembalikan struktur yang berbeda. Letakkan setiap sumber di balik adapter kecil yang mengembalikan model HotelOffer yang sama.
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"),
)
Endpoint dan pemetaan bidang di atas mewakili batas adapter; ganti dengan kontrak tepat dari penyedia yang disetujui Anda. Jangan menciptakan bidang penyedia dalam kode produksi.
Kesalahan perbandingan harga biasanya berasal dari kondisi yang tidak sesuai, bukan aritmetika. Kelompokkan tawaran hanya ketika mereka berbagi properti yang sama, tanggal menginap, jumlah tamu, kategori kamar, dan batasan tarif.
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"],
),
)
Konversi mata uang dengan sumber yang berwaktu dan pertahankan jumlah asli. Jangan membandingkan tarif sarapan yang dapat dibatalkan dengan tarif kamar yang tidak dapat dibatalkan tanpa penyesuaian eksplisit atau preferensi pengguna.
Panduan web-scraping Python CapSolver berguna saat membangun adapter, sementara glosari CapSolver dapat membantu menyamakan terminologi di seluruh tim.
Tarif hotel berubah berdasarkan properti, tanggal, tekanan inventaris, dan jendela pemesanan. Gunakan jadwal yang didorong kebijakan alih-alih polling setiap properti pada frekuensi yang sama.
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
Pengatur waktu produksi juga harus mempertimbangkan batasan penyedia, prioritas properti, volatilitas harga terbaru, dan pengaturan pemberitahuan pengguna. Jitter waktu mulai tugas untuk menghindari lonjakan permintaan.
Hindari memberi notifikasi pada perbedaan kecil dalam mata uang atau pembulatan. Bandingkan total keseluruhan dan perubahan kebijakan yang signifikan.
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,
}
Ambang batas harus mencerminkan aplikasi. Program perjalanan korporat mungkin peduli dengan perubahan kebijakan kecil, sementara pemberitahuan konsumen mungkin menekankan pengurangan harga total yang lebih besar.
Beberapa alur kerja yang disetujui perlu memverifikasi tarif yang ditampilkan publik atau mengumpulkan bidang yang tidak tersedia melalui API yang dikontrak. Gunakan pengumpulan browser cadangan hanya ketika ketentuan situs dan perjanjian Anda memungkinkan.
Dokumentasi CapSolver Agent yang disediakan pengguna memetakan pemulihan browser ke detect() dan solve_on_page() dalam capsolver-core:
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}
Pertahankan konteks browser yang diizinkan yang sama, pertahankan tingkat permintaan yang konservatif, dan hentikan setelah satu upaya pemulihan yang dibatasi. FAQ pemecahan CAPTCHA CapSolver menjelaskan siklus tugas umum, dan FAQ penyelesaian masalah CapSolver menutupi kondisi kegagalan umum.
Kode Bonus: Gunakan kode WEBS di Dashboard CapSolver untuk mendapatkan bonus tambahan 5% pada setiap recharge.
Agen perjalanan AI harus menerima snapshot yang ringkas dan didukung bukti daripada payload penyedia mentah.
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": [
"Tarif mungkin berubah sebelum pemesanan.",
"Verifikasi total, ketersediaan, dan ketentuan pembatalan saat checkout.",
],
}
Ajukan agen untuk menjelaskan pertukaran antara harga dan fleksibilitas. Ia tidak boleh menyatakan bahwa kamar telah dipesan atau bahwa tarif dijamin kecuali endpoint pemesanan atau pemeriksaan harga penyedia telah memverifikasi itu.
Pemantauan bersifat baca saja. Pemesanan mengubah inventaris, menciptakan kewajiban keuangan, dan biasanya memerlukan data pribadi. Pertahankan kemampuan ini dalam layanan terpisah dan minta konfirmasi eksplisit sebelum memanggil endpoint pemesanan apa pun.
| Tahap | Tingkat otomatisasi | Kontrol yang diperlukan |
|---|---|---|
| Pengumpulan tarif | Otomatis | Sumber yang disetujui dan batas kecepatan |
| Normalisasi | Otomatis | Validasi skema dan asal usul |
| Generasi pemberitahuan | Otomatis | Ambang batas yang ditentukan pengguna |
| Rekomendasi | Dibantu | Kriteria perbandingan transparan |
| Pemeriksaan ulang harga | Otomatis sebelum pembelian | Konfirmasi penyedia terbaru |
| Pemesanan dan pembayaran | Dikonfirmasi manusia | Otentikasi dan persetujuan eksplisit |
Batas ini mencegah agen AI dari mengubah pengamatan pemantauan yang usang menjadi pembelian yang tidak diinginkan.
Lacak kepercayaan kesesuaian properti, latensi sumber, pajak yang hilang, waktu konversi mata uang, kunci tarif duplikat, versi parser, dan kesalahan pengumpulan. Pertahankan respons penyedia mentah atau hash integritas ketika lisensi memungkinkan. Ketika properti tidak dapat disesuaikan secara percaya di antara sumber, arahkan ke ulasan alih-alih menggabungkan catatan hanya berdasarkan nama.
Metrik yang berguna termasuk pengamatan sukses per sumber, tarif tidak lengkap, latensi pengumpulan median, tingkat perubahan harga signifikan, tingkat tantangan yang dihadapi, dan volume ulasan manusia. Metrik ini mengungkap masalah kualitas data sebelum memengaruhi rekomendasi.
Gunakan pemantauan harga hotel hanya dengan API, feed, situs web, dan akun yang diizinkan. Ikuti perjanjian mitra, ketentuan situs web, batas cache, aturan harga konsumen regional, dan persyaratan privasi. Jangan mengumpulkan data reservasi pribadi atau informasi akun loyalitas tanpa persetujuan eksplisit. Minimalkan lalu lintas browser dan utamakan antarmuka struktur resmi ketika tersedia.
Data pemantauan harga hotel yang andal membutuhkan lebih dari mengumpulkan angka dari halaman. Agen perjalanan AI membutuhkan kondisi masa inap yang dinormalisasi, total keseluruhan, detail kebijakan, timestamp, dan asal usul sumber. API hotel dan GDS resmi harus menjadi dasar; pengumpulan browser yang diizinkan dapat memberikan penutupan celah terbatas, dengan CapSolver bertindak sebagai lapisan pemulihan yang terkendali ketika tantangan yang didukung mengganggu sesi.
Bangun alur kerja pertama yang disetujui dengan CapSolver, lalu tambahkan adapter khusus penyedia, ambang batas perubahan harga, dan pemeriksaan ulang wajib sebelum tindakan pemesanan.
Paling tidak, simpan ID properti, tanggal menginap, jumlah tamu, tipe kamar, paket makanan, refundabilitas, tenggat waktu pembatalan, mata uang, pajak, biaya, harga total, sumber, dan timestamp pengumpulan.
Gunakan API resmi dan aliran mitra terlebih dahulu. Pengumpulan melalui browser harus dibatasi pada halaman publik yang diizinkan atau tugas QA dan validasi yang disetujui ketika akses terstruktur tidak dapat menyediakan bidang yang diperlukan.
Gunakan kebijakan berdasarkan jendela pemesanan, volatilitas harga, batasan penyedia, dan urgensi peringatan. Periksa masa menginap dekat lebih sering dan masa menginap jauh lebih jarang.
Tidak. Verifikasi harga dan ketersediaan kembali melalui penyedia sebelum pemesanan, dan minta konfirmasi pengguna yang jelas sebelum membuat reservasi atau kewajiban pembayaran.
CapSolver adalah lapisan pemulihan terkendali untuk tantangan yang didukung dalam sesi browser yang diizinkan. Ia tidak menggantikan hak akses penyedia, batasan laju, API, atau konfirmasi pemesanan.
Pelajari arsitektur pengambilan data web Rust yang dapat diskalakan dengan reqwest, scraper, pengambilan data asinkron, pengambilan data browser tanpa tampilan, rotasi proxy, dan penanganan CAPTCHA yang sesuai aturan.

Mengotomasi penyelesaian CAPTCHA dengan Nanobot dan CapSolver. Gunakan Playwright untuk menyelesaikan reCAPTCHA dan Cloudflare secara otomatis.
