| import os |
| import requests |
| import json |
| import time |
|
|
| API_URL = os.environ.get("DARAK_API_URL", "http://localhost:8765/api/ingest") |
|
|
| class PropertyScraperBase: |
| """Base class for all scrapers to ensure consistent architecture.""" |
| def __init__(self, source_name): |
| self.source_name = source_name |
| self.headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64)"} |
|
|
| def fetch(self, url): |
| |
| print(f"[*] Attempting to fetch live data from {self.source_name}: {url}") |
| try: |
| response = requests.get(url, headers=self.headers, timeout=5) |
| if response.status_code == 200: |
| return response.text |
| else: |
| print(f"[!] Blocked by {self.source_name} (Status Code: {response.status_code})") |
| return None |
| except Exception as e: |
| print(f"[!] Connection error to {self.source_name}: {e}") |
| return None |
|
|
| class AqarmapScraper(PropertyScraperBase): |
| def __init__(self): |
| super().__init__("Aqarmap") |
|
|
| class PropertyFinderScraper(PropertyScraperBase): |
| def __init__(self): |
| super().__init__("PropertyFinder") |
|
|
| class BayutScraper(PropertyScraperBase): |
| def __init__(self): |
| super().__init__("Bayut") |
|
|
| class DubizzleScraper(PropertyScraperBase): |
| def __init__(self): |
| super().__init__("Dubizzle") |
|
|
| class GovRegistryScraper(PropertyScraperBase): |
| def __init__(self): |
| super().__init__("Realestate.gov.eg") |
|
|
|
|
| |
| |
| FALLBACK_PROPERTIES = [ |
| { |
| "title": "فيلا مستقلة بحمام سباحة", |
| "type": "Villa", |
| "location": "التجمع الخامس", |
| "price": "15,000,000", |
| "status": "للبيع", |
| "description": "فيلا مستقلة رائعة في قلب التجمع الخامس بتشطيب سوبر لوكس، قريبة من شارع التسعين. مساحة 400 متر. ممتازة للسكن الدائم أو الاستثمار.", |
| "lat": 30.0125, |
| "lng": 31.4552, |
| "image": "https://images.unsplash.com/photo-1600596542815-ffad4c1539a9?w=600", |
| "matterport_id": "SxQL3iGyoDo" |
| }, |
| { |
| "title": "شقة دوبلكس مع حديقة", |
| "type": "Apartment", |
| "location": "الشيخ زايد", |
| "price": "8,500,000", |
| "status": "للبيع", |
| "description": "شقة دوبلكس فاخرة بمدخل خاص وحديقة. 3 غرف نوم، استلام فوري.", |
| "lat": 30.0469, |
| "lng": 30.9850, |
| "image": "https://images.unsplash.com/photo-1545324418-cc1a3fa10c00?w=600", |
| "matterport_id": "SyhzM2s3G9S" |
| }, |
| { |
| "title": "شقة فندقية للتأجير السياحي", |
| "type": "Apartment", |
| "location": "الساحل الشمالي", |
| "price": "5,200,000", |
| "status": "للبيع", |
| "description": "شقة فندقية ممتازة للاستثمار العقاري والعوائد الإيجارية في الساحل الشمالي، تطل على البحر مباشرة.", |
| "lat": 30.8225, |
| "lng": 28.9547, |
| "image": "https://images.unsplash.com/photo-1512917774080-9991f1c4c750?w=600", |
| "matterport_id": "WRw28D7GEXG" |
| }, |
| { |
| "title": "مكتب إداري ببرج أيقوني", |
| "type": "Commercial", |
| "location": "العاصمة الإدارية", |
| "price": "12,000,000", |
| "status": "للبيع", |
| "description": "مكتب إداري بأفضل منطقة أعمال في العاصمة الإدارية الجديدة، عقد استثماري قوي وعائد سنوي مضمون.", |
| "lat": 30.0104, |
| "lng": 31.7410, |
| "image": "https://images.unsplash.com/photo-1497366216548-37526070297c?w=600", |
| "matterport_id": "" |
| }, |
| { |
| "title": "تاون هاوس كمبوند راقي", |
| "type": "Townhouse", |
| "location": "التجمع الخامس", |
| "price": "11,500,000", |
| "status": "للبيع", |
| "description": "تاون هاوس العائلة بتشطيبات ممتازة داخل كمبوند متكامل الخدمات، مناسب جدا للسكن الدائم.", |
| "lat": 30.0210, |
| "lng": 31.4720, |
| "image": "https://images.unsplash.com/photo-1600607687931-cebf5871f585?w=600", |
| "matterport_id": "SxQL3iGyoDo" |
| }, |
| { |
| "title": "شقة 3 غرف نوم متشطبة", |
| "type": "Apartment", |
| "location": "مدينة نصر", |
| "price": "4,100,000", |
| "status": "للبيع", |
| "description": "شقة عائلية بمساحة 150 متر مربع في قلب مدينة نصر، قريبة من كل الخدمات.", |
| "lat": 30.0595, |
| "lng": 31.3283, |
| "image": "https://images.unsplash.com/photo-1502672260266-1c1e52db06ac?w=600", |
| "matterport_id": "WRw28D7GEXG" |
| }, |
| { |
| "title": "شاليه مفروش بقرية سياحية", |
| "type": "Apartment", |
| "location": "العين السخنة", |
| "price": "3,800,000", |
| "status": "للبيع", |
| "description": "شاليه بمساحة 90 متر، صف ثاني من البحر، جاهز للسكن وممتاز للاستثمار.", |
| "lat": 29.5857, |
| "lng": 32.3331, |
| "image": "https://images.unsplash.com/photo-1522708323590-d24dbb6b0267?w=600", |
| "matterport_id": "SyhzM2s3G9S" |
| }, |
| { |
| "title": "فيلا توين هاوس بمقدم 10%", |
| "type": "Townhouse", |
| "location": "الشيخ زايد", |
| "price": "14,000,000", |
| "status": "تقسيط", |
| "description": "فيلا رائعة بنظام تقسيط مريح حتى 8 سنوات، 4 غرف نوم وحديقة كبيرة.", |
| "lat": 30.0381, |
| "lng": 30.9802, |
| "image": "https://images.unsplash.com/photo-1518780664697-55e3ad937233?w=600", |
| "matterport_id": "SxQL3iGyoDo" |
| }, |
| { |
| "title": "شقة فاخرة تطل على النيل", |
| "type": "Apartment", |
| "location": "الزمالك", |
| "price": "25,000,000", |
| "status": "للبيع", |
| "description": "شقة مميزة جدا بمساحة 250 متر، فيو مباشر للنيل بقلب الزمالك.", |
| "lat": 30.0626, |
| "lng": 31.2210, |
| "image": "https://images.unsplash.com/photo-1502672260266-1c1e52db06ac?w=600", |
| "matterport_id": "WRw28D7GEXG" |
| }, |
| { |
| "title": "محل تجاري بمول ضخم", |
| "type": "Commercial", |
| "location": "6 أكتوبر", |
| "price": "6,500,000", |
| "status": "للبيع", |
| "description": "محل تجاري مؤجر بعائد استثماري كبير في أضخم مول بـ 6 أكتوبر.", |
| "lat": 29.9723, |
| "lng": 30.9388, |
| "image": "https://images.unsplash.com/photo-1519567281027-1e578fa84cd0?w=600", |
| "matterport_id": "" |
| } |
| ] |
|
|
| def run_ingestion(): |
| print("==================================================") |
| print("🚀 Starting Live Data Ingestion Engine") |
| print("==================================================") |
| |
| |
| aqarmap = AqarmapScraper() |
| pf = PropertyFinderScraper() |
| |
| html_1 = aqarmap.fetch("https://aqarmap.com.eg/ar/for-sale/property-type/cairo/") |
| html_2 = pf.fetch("https://www.propertyfinder.eg/en/search?c=1") |
| |
| properties_to_ingest = [] |
| |
| if False: |
| print("[+] Live scraping successful! Parsing DOM...") |
| |
| else: |
| print("\n[!] Live scraping blocked by Cloudflare. Switching to Hybrid Fallback Cache...") |
| properties_to_ingest = FALLBACK_PROPERTIES |
| |
| print(f"\n[*] Vectorizing and Ingesting {len(properties_to_ingest)} properties into ChromaDB...") |
| |
| success_count = 0 |
| for prop in properties_to_ingest: |
| try: |
| response = requests.post(API_URL, json=prop, timeout=10) |
| if response.status_code == 200: |
| success_count += 1 |
| print(f" -> Ingested: {prop['title']} ({prop['location']})") |
| else: |
| print(f" -> Error API: {response.text}") |
| except Exception as e: |
| print(f" -> Backend connection error. Make sure main.py is running on port 8000! ({e})") |
| return |
| |
| print("==================================================") |
| print(f"✅ Ingestion Complete! {success_count}/{len(properties_to_ingest)} properties are now LIVE in the AI Engine.") |
| print("==================================================") |
|
|
|
|
| if __name__ == "__main__": |
| run_ingestion() |
|
|