Real estate data scraping - collect property listings with Python and proxies - DataImpulse

تجريف بيانات العقارات هو ما يمكّن منصات العقارات والمستثمرين وفرق التقنية العقارية من تحويل القوائم المتفرقة على الإنترنت إلى مجموعة بيانات منظّمة، تشمل الأسعار والعناوين وغرف النوم والحمّامات والمساحة بالقدم المربع والاتجاهات في سوق كامل. يوضح هذا الدليل كيفية تجريف قوائم العقارات باستخدام Python بطريقة موثوقة، عبر تحليل البيانات المنظّمة التي تضمّنها المواقع بالفعل، إلى جانب إعدادات مكافحة الروبوتات والبروكسي التي تُبقي عملية الجمع مستمرة عبر المناطق.

أنا Andrii Byzov، مدير تسويق جزئي يعمل بالذكاء الاصطناعي، وأبني مسارات بيانات الويب. ستجد أدناه بيانات العقارات التي يمكنك جمعها، وحدوداً قانونية واضحة، وشيفرة عملية لنتائج البحث والقوائم الفردية، مع بروكسيات سكنية لبيانات دقيقة جغرافياً وغير محجوبة.


حقائق أساسية

  • معظم معلومات القوائم عامة وأقل خطورة، مثل السعر وغرف النوم والحمّامات والمساحة بالقدم المربع والنوع، لكن العناوين والصور والأوصاف وأسماء الوكلاء قد تكون بيانات شخصية أو محمية بحقوق النشر، لذا قيّمها قبل إعادة استخدامها.
  • حلّل JSON المضمّن عند توفره، بدلاً من CSS الهش. تعرض كثير من مواقع العقارات بيانات القوائم بصيغة JSON-LD ‏(schema.org)، فحلّلها عند توفرها وعُد إلى بطاقات HTML عند عدم توفرها.
  • تخصّص بعض المواقع المحتوى بحسب الموقع، مثل النتائج والتوفر واللغة أو العملة، لذا تساعد البروكسيات المستهدفة جغرافياً على مطابقة سوق محددة.
  • البوابات الكبيرة محمية بقوة. تفرض Zillow وRealtor.com وRightmove ومواقع مشابهة حدوداً للمعدل وتعلّم عناوين IP الخاصة بمراكز البيانات بسرعة. تساعد البروكسيات السكنية الدوّارة، لكن لا توجد أداة تضمن الوصول أو الامتثال.
  • بيانات اتصال الوكلاء والملاك بيانات شخصية. أبقها خارج مسار المعالجة، واجمع معلومات العقار لا معلومات الأشخاص.

ما بيانات العقارات التي يمكنك تجريفها؟

قائمة العقار بيانات غنية ومنظّمة. إليك الحقول التي تستحق الجمع عادةً، وتلك التي ينبغي التعامل معها بحذر:

  • معلومات العقار الأقل خطورة: السعر، وغرف النوم، والحمّامات، والمساحة بالقدم المربع، ومساحة الأرض، ونوع العقار، وسنة البناء، وحالة القائمة، والأيام في السوق، وسجل الأسعار.
  • تعامل معها بحذر أو تجنبها: العناوين الدقيقة والصور والأوصاف الكاملة، التي غالباً ما تكون محمية بحقوق النشر، وبيانات اتصال الوكلاء والملاك، وهي بيانات شخصية. لا تجعل الإتاحة العامة هذه البيانات قابلة لإعادة الاستخدام تلقائياً.

هل تجريف بيانات العقارات قانوني؟

إن جمع معلومات العقارات العامة قابل للدفاع عنه على نطاق واسع، وهو أساس عمل ذكاء الأسعار والتقنية العقارية، لكن الإتاحة العامة لا تجعل البيانات غير شخصية أو قابلة لإعادة الاستخدام تلقائياً. قيّم الخصوصية وحقوق النشر وحقوق قواعد البيانات والعقود والقانون المحلي. القاعدة العملية: لا تجرّف ما وراء تسجيل الدخول، وأبق البيانات الشخصية، مثل بيانات الوكيل أو المالك، خارج العملية، ولا تعِد نشر الصور أو الأوصاف المحمية بحقوق النشر، واحترم شروط كل موقع وrobots.txt، ولا تتحايل على ضوابط الوصول أو اختبارات CAPTCHA. تقيّد البوابات الكبيرة الوصول الآلي، لذا يُفضّل لها استخدام API رسمي أو موجز بيانات مرخّص أو إذن كتابي. للاطلاع على الإطار الكامل، راجع دليلنا حول مدى قانونية تجريف الويب. هذه معلومات عامة وليست استشارة قانونية.


الخطوة 1: إعداد بيئتك

ثبّت المكتبات التي يحتاجها مجرّف بيانات العقارات. تعمل المواقع الثابتة المتوافقة مع JSON-LD باستخدام requests، بينما تحتاج البوابات الكثيفة الاستخدام لـ JavaScript، مثل Zillow، إلى متصفح بلا واجهة.



# Core libraries for real estate data scraping
# requests -> fetch pages | beautifulsoup4 + lxml -> parse HTML/JSON
pip install requests beautifulsoup4 lxml

# Many listing sites are JavaScript-heavy and well defended (e.g. Zillow).
# For those, add a headless browser:
pip install playwright && playwright install chromium







الخطوة 2: جلب صفحة القوائم

اجلب صفحة نتائج بحث، أي URL لمنازل معروضة للبيع في مدينة، باستخدام ترويسات مناسبة، ومرّرها عبر بروكسي سكني كي تطابق القوائم السوق المستهدفة.



import requests

HEADERS = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) "
                         "AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36",
           "Accept-Language": "en-US,en;q=0.9"}

# Route through residential proxies for geo-accurate listings (see Step 5)
proxies = {"http":  "http://LOGIN:[email protected]:823",
           "https": "http://LOGIN:[email protected]:823"}

def get_html(url):
    r = requests.get(url, headers=HEADERS, proxies=proxies, timeout=30)
    r.raise_for_status()
    return r.text

html = get_html("https://example-realestate.com/homes/for_sale/CityName/")
















الخطوة 3: استخراج القوائم من JSON المضمّن

عند توفرها، فإن أكثر الطرق موثوقية لتجريف قوائم العقارات هي قراءة البيانات المنظّمة التي يضمّنها الموقع بالفعل. تتضمن كثير من منصات العقارات application/ld+json ‏(schema.org) مع سعر القائمة وعنوانها وURL الخاص بها، وهي ثابتة عبر عمليات إعادة التصميم بخلاف أسماء فئات CSS. لا يعرضها كل موقع، إذ يحتفظ بعضها بالبيانات في حالة تطبيق JS، لذا تحقّق من كل موقع وعُد إلى تحليل البطاقات في الخطوة 4.



import json
from bs4 import BeautifulSoup

LISTING_TYPES = ("Residence", "Product", "RealEstateListing", "Offer",
                 "SingleFamilyResidence", "Apartment", "House")

def listings_from_jsonld(html):
    """Where available, sites embed listing data as JSON-LD (schema.org).
    Parsing it is more stable than CSS classes — but not every site has it,
    so fall back to the cards in Step 4 when this returns nothing."""
    soup = BeautifulSoup(html, "lxml")
    nodes, out = [], []
    for tag in soup.find_all("script", type="application/ld+json"):
        try:
            data = json.loads(tag.string or "{}")
        except json.JSONDecodeError:
            continue
        stack = data if isinstance(data, list) else [data]
        while stack:                      # flatten @graph / ItemList / nested
            n = stack.pop()
            if not isinstance(n, dict):
                continue
            if "@graph" in n:
                stack.extend(n["@graph"])
            if n.get("@type") == "ItemList":
                stack.extend(x.get("item", x) for x in n.get("itemListElement", []))
            nodes.append(n)
    for n in nodes:
        types = n.get("@type", "")
        types = types if isinstance(types, list) else [types]
        if any(t in LISTING_TYPES for t in types):
            offers = n.get("offers") or {}
            if isinstance(offers, list):
                offers = offers[0] if offers else {}
            out.append({"name": n.get("name"),
                        "price": offers.get("price") or n.get("price"),
                        "address": n.get("address"),
                        "url": n.get("url")})
    return out

print(listings_from_jsonld(html)[:3])









































الخطوة 4: تحليل بطاقات القوائم، كخيار احتياطي

عندما لا يعرض الموقع JSON-LD نظيفاً، حلّل بطاقات نتائج البحث مباشرةً: السعر والعنوان وغرف النوم والحمّامات والمساحة بالقدم المربع ورابط القائمة. تختلف المحددات حسب الموقع وتتغير كثيراً، لذا تأكد منها في DevTools.



def parse_listing_cards(html):
    """Fallback: parse the search-results cards directly. Selectors differ by
    site and change often — confirm the current ones in DevTools."""
    soup = BeautifulSoup(html, "lxml")
    cards = []
    for card in soup.select("[data-test='property-card']"):
        def t(sel):
            el = card.select_one(sel)
            return el.get_text(strip=True) if el else None
        cards.append({
            "price":   t("[data-test='property-price']"),
            "address": t("[data-test='property-address']"),
            "beds":    t("[data-test='property-beds']"),
            "baths":   t("[data-test='property-baths']"),
            "sqft":    t("[data-test='property-sqft']"),
            "url":     (card.select_one("a[href]") or {}).get("href"),
        })
    return cards


















الخطوة 5: التعامل مع ترقيم الصفحات

صفحة واحدة من النتائج ليست مجموعة بيانات. انتقل عبر الصفحات حتى تنفد النتائج أو تبلغ حداً معيناً، ونظّم وتيرة الطلبات حتى لا تتجاوز حدود المعدل.



import time, random

def scrape_all_pages(base_url, max_pages=10):
    """Page through search results until empty or max_pages."""
    all_listings = []
    for page in range(1, max_pages + 1):
        html = get_html(f"{base_url}?page={page}")
        cards = parse_listing_cards(html)
        if not cards:        # no more results -> stop
            break
        all_listings.extend(cards)
        time.sleep(random.uniform(1, 3))   # pace requests
    return all_listings













الخطوة 6: استخدام البروكسيات لبيانات دقيقة جغرافياً وغير محجوبة

هناك أمران يجعلان تجريف الويب للعقارات أصعب دون بروكسيات. الأول هو الموقع: تخصّص بعض المواقع النتائج أو التوفر أو اللغة أو العملة حسب المنطقة، لذا تستعلم من عنوان IP في تلك المنطقة لمطابقة سوق محددة. والثاني هو الحجب: تعلّم البوابات الكبيرة عناوين IP الخاصة بمراكز البيانات بسرعة وتفرض حدوداً صارمة للمعدل. تساعد بروكسيات DataImpulse السكنية، بسعر $1/GB وبتدوير عبر 195 دولة مع استهداف المدينة أو الولاية، في الأمرين معاً، فهي عناوين IP لمستخدمين حقيقيين في السوق المناسبة وتقلل الحجب القائم على IP. ومع ذلك، لا يكون الوصول مضموناً، ولا يزال يتعين عليك اتباع قواعد كل موقع. مرّر الطلبات عبرها وصدّر البيانات التي جمعتها.



import time, random, json, csv

# Listings differ by region: route through a proxy in the target market so
# prices, availability, and currency match what a local user sees.
proxies = {
    "http":  "http://LOGIN__cr.us;sid.re1:[email protected]:823",
    "https": "http://LOGIN__cr.us;sid.re1:[email protected]:823",
}

listings = scrape_all_pages("https://example-realestate.com/homes/for_sale/CityName/")

with open("listings.json", "w", encoding="utf-8") as f:
    json.dump(listings, f, indent=2, ensure_ascii=False)
if listings:
    with open("listings.csv", "w", newline="", encoding="utf-8") as f:
        w = csv.DictWriter(f, fieldnames=listings[0].keys())
        w.writeheader(); w.writerows(listings)

















الأسئلة الشائعة

هل تجريف بيانات العقارات قانوني؟

إن جمع بيانات العقارات العامة وغير الشخصية، مثل السعر والعنوان وغرف النوم والمساحة بالقدم المربع، قابل للدفاع عنه على نطاق واسع ومعتاد في التقنية العقارية. تجنب البيانات الشخصية، مثل بيانات اتصال الوكيل أو المالك، ولا تجرّف ما وراء تسجيلات الدخول، ولا تعِد نشر الصور أو الأوصاف المحمية بحقوق النشر، واحترم شروط الموقع وrobots.txt. تقيّد البوابات الكبيرة الوصول الآلي، لذا احصل على إذن أو استشارة للاستخدام التجاري. هذه معلومات عامة وليست استشارة قانونية، راجع دليل قانونية تجريف الويب.

ما أفضل طريقة لتجريف قوائم العقارات؟

حلّل البيانات المنظّمة التي تضمّنها المواقع بالفعل، إذ تقدّم معظم منصات العقارات القوائم بصيغة JSON-LD ‏(schema.org) في HTML الصفحة، وهي أكثر ثباتاً بكثير من تتبع أسماء فئات CSS التي تتغير مع كل إعادة تصميم. لا تلجأ إلى تحليل بطاقات القوائم إلا عند عدم توفر JSON نظيف.

هل أحتاج إلى بروكسيات لتجريف مواقع العقارات؟

عادةً نعم، عند العمل بكميات كبيرة. تفرض البوابات الكبيرة، مثل Zillow وRealtor.com وRightmove، حدوداً للمعدل وتعلّم عناوين IP الخاصة بمراكز البيانات سريعاً، كما تعتمد بعض القوائم على الموقع. تساعد البروكسيات السكنية الدوّارة في السوق المستهدفة على إرجاع بيانات دقيقة للموقع وتقليل الحجب القائم على IP، لكنها لا تضمن الوصول ولا تجعل التجريف ممتثلاً تلقائياً.

هل يمكنني تجريف Zillow أو Realtor.com مباشرةً؟

هي عامة لكنها محمية بقوة وتُعرَض باستخدام JavaScript، كما تقيد شروطها الوصول الآلي. بالنسبة إلى تلك البوابات، فضّل API رسمياً أو موجز بيانات مرخّصاً أو إذناً كتابياً بدلاً من التحايل على دفاعاتها. إذا جمعت بيانات عامة، فخذ معلومات العقارات العامة فقط، وابقَ مسجلاً للخروج، ولا تتجاوز ضوابط الوصول، ونظّم وتيرة الطلبات. راجع دليلنا حول أفضل بروكسيات لـ Zillow.

ما بيانات العقارات التي يمكنني جمعها؟

في الغالب معلومات العقارات العامة، مثل السعر وغرف النوم والحمّامات والمساحة بالقدم المربع ومساحة الأرض والنوع والحالة والأيام في السوق وسجل الأسعار. لكن الإتاحة العامة لا تجعل البيانات غير شخصية أو قابلة لإعادة الاستخدام تلقائياً: فقد تنطوي العناوين الدقيقة والصور والأوصاف وبيانات الوكلاء والملاك على اعتبارات خصوصية أو حقوق نشر، لذا قيّمها قبل التخزين أو إعادة النشر.


الخلاصة

يحوّل تجريف بيانات العقارات القوائم المتفرقة إلى مجموعة بيانات قابلة للاستخدام. والوصفة الموثوقة هي: اقرأ JSON-LD المضمّن حيثما أمكن، وعُد إلى تحليل البطاقات حيث لا يمكن، وانتقل عبر النتائج، ومرّر كل شيء عبر بروكسيات سكنية مستهدفة جغرافياً كي تكون البيانات دقيقة للموقع وغير محجوبة. التزم بمعلومات العقارات العامة وغير الشخصية لتبقى ضمن المسار القابل للدفاع عنه. وللبنية التحتية، راجع أفضل بروكسيات لبيانات العقارات ودليل أفضل بروكسيات لتجريف الويب الأوسع.

آخر تحديث: 25 يونيو 2026.



Share article: