قائمة وثائق المطورين

شبكة الأحياء باستخدام مستطيلات الخريطة

متقدم

قسّم المدينة إلى خلايا شبكية، واستعلم عن كل خلية بمستطيل حدود، وصدّر النتائج بصيغة GeoJSON لعرضها على خريطة.

الإعداد

يستخدم هذا الدرس الأداة المساعدة jokerprice.py من درس البدء السريع. احفظها بجوار نصك البرمجي واضبط JOKERPRICE_API_KEY.

استعلامات مستطيل الحدود

تقبل /api/v1/metrics المعاملات north وsouth وeast وwest بدلًا من city. يجب ألا يتجاوز عرض المستطيل 5 درجات، وأن يكون الجنوب أدنى من الشمال والغرب أدنى من الشرق.

Python
from jokerprice import api

box = {"north": 24.85, "south": 24.70, "east": 46.80, "west": 46.60}   # central and north Riyadh
m = api("GET", "/api/v1/metrics", params={**box, "past_days": 60})["metrics"]
print(m["listings"]["tracked"], "tracked listings |", m["maturity"], "| occupancy", m["past"]["occupancy"])

ابنِ الشبكة

كل خلية طلب واحد؛ فالشبكة 4 × 4 تعني 16 طلبًا، وتنتظر الأداة المساعدة تلقائيًا إذا بلغت 120 طلبًا في الدقيقة.

Python
def grid(box, rows, cols):
    lat_step = (box["north"] - box["south"]) / rows
    lng_step = (box["east"] - box["west"]) / cols
    for r in range(rows):
        for c in range(cols):
            south, west = box["south"] + r * lat_step, box["west"] + c * lng_step
            yield {"south": round(south, 5), "north": round(south + lat_step, 5), "west": round(west, 5), "east": round(west + lng_step, 5)}

cells = []
for cell in grid(box, 4, 4):
    m = api("GET", "/api/v1/metrics", params={**cell, "past_days": 60})["metrics"]
    cells.append({**cell, "tracked": m["listings"]["tracked"], "maturity": m["maturity"],
                  "occupancy": m["past"]["occupancy"], "adr": m["past"]["adr"]})

صدّر GeoJSON

اكتب الخلايا على هيئة مضلعات. افتح الملف في geojson.io أو QGIS أو kepler.gl ولوّنه حسب الإشغال. تبقى الخلايا التي ما زالت قيد الجمع موجودة مع وسمها، لتظل المناطق الفارغة ظاهرة.

Python
import json

features = []
for c in cells:
    ring = [[c["west"], c["south"]], [c["east"], c["south"]], [c["east"], c["north"]], [c["west"], c["north"]], [c["west"], c["south"]]]
    ok = c["maturity"] == "estimating"
    features.append({"type": "Feature", "geometry": {"type": "Polygon", "coordinates": [ring]},
                     "properties": {"tracked": c["tracked"], "maturity": c["maturity"],
                                    "occupancy": round(c["occupancy"], 3) if ok else None,
                                    "adr": round(c["adr"]) if ok and c["adr"] else None}})
json.dump({"type": "FeatureCollection", "features": features}, open("riyadh-grid.geojson", "w"))

العقارات داخل مستطيل

تصفّي /api/v1/listings حسب المدينة فقط، لذا صفِّ الإحداثيات بنفسك.

Python
from jokerprice import all_listings

inside = lambda l, b: l.get("latitude") is not None and b["south"] <= l["latitude"] <= b["north"] and b["west"] <= l["longitude"] <= b["east"]
listings = [l for l in all_listings("riyadh") if inside(l, box)]
print(len(listings), "listings in the box")