البدء السريع: الأسواق والمؤشرات والتقدير
مبتدئ
نفّذ أول طلباتك بلغة Python أو JavaScript واربط نقاط الوصول الأساسية معًا.
قبل أن تبدأ
تحتاج إلى حساب جوكر برايس، ومفتاح API من صفحة البيانات وواجهة API (Data & API)، وPython 3.9 أو أحدث مع مكتبة requests، أو Node 18 أو أحدث. احفظ المفتاح في متغير بيئة حتى لا يظهر أبدًا في شيفرتك.
export JOKERPRICE_API_KEY="ss_your_key_here"
pip install requestsأنشئ عميلًا صغيرًا
يحتاج كل طلب إلى الترويسة نفسها ومعالجة الأخطاء نفسها، فاجمعهما في مكان واحد. وتنتظر الأداة المساعدة وتعيد المحاولة عند بلوغ حد الدقيقة (120 خلال التجربة المجانية)، أما الحد اليومي (25,000 خلال التجربة المجانية) فيُطلق خطأً بدلًا من ذلك.
# jokerprice.py: a small client for the JokerPrice API.
import os, time, requests
BASE = "https://jokerprice.com"
session = requests.Session()
session.headers["Authorization"] = "Bearer " + os.environ["JOKERPRICE_API_KEY"]
def api(method, path, **kwargs):
"""Call an /api/v1 endpoint and return its JSON. Waits and retries when the per-minute limit is hit."""
while True:
res = session.request(method, BASE + path, timeout=60, **kwargs)
body = res.json()
if res.status_code == 429 and body["error"]["code"] == "RATE_LIMIT":
time.sleep(int(res.headers.get("Retry-After", "60")))
continue
if not res.ok:
raise RuntimeError(f"{res.status_code} {body['error']['code']}: {body['error']['message']}")
return body
def all_listings(city):
"""Every listing for a city, following nextCursor page by page (500 per request)."""
out, cursor = [], None
while True:
params = {"city": city, "limit": 500}
if cursor:
params["cursor"] = cursor
page = api("GET", "/api/v1/listings", params=params)
out += page["listings"]
cursor = page["nextCursor"]
if not cursor:
return out// jokerprice.mjs: a small client for the JokerPrice API (Node 18+).
const BASE = "https://jokerprice.com";
const KEY = process.env.JOKERPRICE_API_KEY;
const sleep = ms => new Promise(resolve => setTimeout(resolve, ms));
export async function api(path, { method = "GET", query = {}, body } = {}) {
const url = new URL(BASE + path);
for (const [name, value] of Object.entries(query)) url.searchParams.set(name, String(value));
for (;;) {
const res = await fetch(url, {
method,
headers: { Authorization: "Bearer " + KEY, ...(body ? { "Content-Type": "application/json" } : {}) },
body: body ? JSON.stringify(body) : undefined,
});
const data = await res.json();
if (res.status === 429 && data.error.code === "RATE_LIMIT") { await sleep(Number(res.headers.get("Retry-After") || 60) * 1000); continue; }
if (!res.ok) throw new Error(res.status + " " + data.error.code + ": " + data.error.message);
return data;
}
}اعرض الأسواق
ابدأ بـ /api/v1/markets. تُرجع كل وجهة تضم 20 عقارًا على الأقل، مع المعرّف slug الذي تحتاج إليه نقاط الوصول الأخرى.
from jokerprice import api
markets = api("GET", "/api/v1/markets")["markets"]
for m in markets[:10]:
t = m["tracker"]
occupancy = f"{t['occupancy']:.0%}" if t and t["maturity"] == "estimating" else "collecting"
median = m["nightly"]["median"] or 0
print(f"{m['slug']:<26} {m['listings']:>6} listings median SAR {median:>5.0f} occupancy {occupancy}")تبقى قيمة tracker للسوق null إلى أن يتتبّع جوكر برايس التقويمات فيه، وتبقى قيمة maturity هي "collecting" إلى أن يتوفر سجل كافٍ. لا تعتمد على الإشغال إلا عندما تكون القيمة "estimating".
أداء مدينة واحدة
تُرجع /api/v1/metrics الإشغال ومتوسط السعر اليومي والإيرادات للفترة التي تختارها. يغطي past الليالي السابقة لليوم، ويمثل forward.onTheBooks نسبة الليالي القادمة المحجوزة مسبقًا.
import { api } from "./jokerprice.mjs";
const { metrics } = await api("/api/v1/metrics", { query: { city: "riyadh", past_days: 30, forward_days: 60 } });
console.log("maturity", metrics.maturity);
console.log("occupancy", metrics.past.occupancy, "ADR", metrics.past.adr, "SAR");
console.log("revenue per listing per month", metrics.past.monthlyRevenuePerListing);
console.log("next 60 nights already booked", metrics.forward.onTheBooks);قدّر إيرادات عقار
أرسل الإحداثيات وعدد غرف النوم ومعرّف نوع العقار إلى POST /api/v1/estimate. إذا توفر لدى جوكر برايس إشغال مقيس في المنطقة فستحصل على توقع واحد projection، وإلا فستحصل على ثلاثة سيناريوهات إشغال scenarios.
from jokerprice import api
est = api("POST", "/api/v1/estimate", json={
"latitude": 24.7743, "longitude": 46.7386, # a point in north Riyadh
"bedrooms": 2, "typeId": "6", # 2-bedroom apartment
})["estimate"]
print("comparables:", est["asking"]["count"], " ADR basis:", est["adr"]["basis"])
if est["projection"]:
print(f"Projected: SAR {est['projection']['annual']:,.0f} a year at {est['projection']['occupancy']:.0%}")
elif est["scenarios"]:
for sc in est["scenarios"]:
print(f"At {sc['occupancy']:.0%} occupancy: SAR {sc['annual']:,.0f} a year")
else:
print("No comparables within the radius. Try a larger radiusKm.")الخطوات التالية
- يتعمق درس تقدير الإيرادات في استجابة التقدير.
- يشرح درس التصفية المتقدمة التنقل بين صفحات العقارات وتصفيتها.
- يسرد مرجع نقاط الوصول جميع المعاملات.