يقوم Redfin بتحديث 70% من إعلانات MLS الجديدة في الولايات المتحدة خلال خمس دقائق من ظهورها. هذا المستوى من حداثة البيانات هو حلم كل من يبني خط أنابيب لبيانات العقارات، وهو تحديدًا السبب الذي يجعل الكثير من أدوات التجريف تستهدف Redfin ثم تُحجب خلال دقائق.
قضيت سنوات في العمل على أدوات استخراج البيانات في Thunderbit، ويمكنني أن أخبرك: الفجوة بين «تجريف Redfin» و«تجريف Redfin دون أن تُحجب» هي بالضبط النقطة التي تنهار عندها معظم الشروحات. فهي تعرض عليك كود BeautifulSoup، وتتخطى الجزء الذي تلتهم فيه Cloudflare طلباتك حيّة، وتتركك تحدّق في صفحة 403 متسائلًا عمّا حدث. هذا الدليل مختلف. سأشرح لك ثلاث مقاربات حقيقية: تحليل HTML، وواجهة Redfin المخفية، والمسار بلا أكواد عبر Thunderbit، وسأخصص وقتًا جادًا لدفاعات مكافحة الروبوتات التي تهمّ فعلًا. وبنهاية المقال، ستعرف بالضبط أي طريقة تناسب مستوى مهارتك، وحجم عملك، ومدى تحمّلك لصداع الصيانة.
جرّب Thunderbit لاستخراج بيانات Redfin
ما هو Redfin، ولماذا تهمّ بياناته؟
Redfin هي وساطة عقارية مدعومة بالتقنية، يعمل بها وكلاء برواتب ثابتة يسحبون الإعلانات مباشرةً من تغذيات MLS. وتغطي أكثر من 100 منطقة حضرية في الولايات المتحدة وكندا عبر 42 ولاية وتخدم نحو 50 مليون زائر شهريًا. وعلى عكس البوابات التي تكتفي بالتجميع، بيانات Redfin موثّقة من الوكلاء، ويغطي نموذج التقييم الآلي الخاص بها Redfin Estimate أكثر من 95 مليون عقار بمتوسط خطأ لا يتجاوز 1.96% للمنازل المعروضة حاليًا في السوق.

هذا المزيج — حداثة بسرعة MLS، وجودة موثّقة من الوسطاء، ونموذج تقييم دقيق — هو ما يجعل المستثمرين العقاريين والوكلاء وشركات البروبتك الناشئة ومحللي البيانات جميعًا يرغبون في وصول برمجي إلى بيانات Redfin. وPython هي الخيار الطبيعي لهذه المهمة: منظومة التجريف فيها (requests وBeautifulSoup وSelenium وPlaywright) ناضجة، ودعم المجتمع هائل، وهي تتكامل مباشرةً مع pandas وJupyter للتحليل.
لماذا تجرّف Redfin باستخدام Python؟
حالات الاستخدام متنوعة بتنوّع الأشخاص الذين يحتاجون البيانات. إليك كيف تستخدم الفئات المختلفة بيانات Redfin المجرَّفة عادةً:
| الفئة | الهدف الأساسي من التجريف | مثال على حالة الاستخدام |
|---|---|---|
| الوكلاء العقاريون | توليد العملاء المحتملين، استخبارات السوق | الإعلانات الجديدة والمنتهية في منطقة الخدمة؛ دليل الوكلاء للمقارنة التنافسية |
| المستثمرون العقاريون | تدفق الصفقات، تحليل معدل الرسملة | فلاتر العائد الإيجاري، رصد العقارات المقوَّمة بأقل من قيمتها، تنبيهات يومية بالإعلانات الجديدة |
| شركات البروبتك الناشئة | خطوط أنابيب بيانات المنتج | بيانات تدريب نماذج التقييم، لوحات معلومات السوق، محركات الاستحواذ لدى iBuyer |
| محللو البيانات | أبحاث السوق، ذكاء الأعمال | اتجاهات متوسط السعر على مستوى الرمز البريدي، السلاسل الزمنية لأيام العرض في السوق، نسب سعر البيع إلى سعر الطلب |
| تجار الجملة / مُعيدو التأهيل | تتبّع العقارات المتعثّرة | رصد تخفيضات الأسعار، حالات حبس الرهن، المقارنات خارج السوق |
والاتجاه العام يدعم ذلك: أكثر من 72% من شركات العقارات تستخدم اليوم التحليلات التنبؤية لتحديد الفرص وإدارة المخاطر. ومن المتوقع أن يصل سوق البروبتك إلى 47 مليار دولار في 2025 بمعدل نمو سنوي مركّب قدره 16.4%. لم تعد بيانات العقارات المنظّمة ميزة إضافية، بل صارت شرطًا أساسيًا للمشاركة.
كل حقل بيانات يمكنك تجريفه من Redfin (مرجع كامل)
قبل أن تكتب سطرًا واحدًا من الكود، عليك أن تعرف ما هو متاح فعليًا. لقد دققت في صفحات نتائج البحث في Redfin، وصفحات تفاصيل العقارات، وملفات الوكلاء، وقارنتها بمغلّفات Stingray API مفتوحة المصدر مثل مشروعَي reteps/redfin وRedfinPlus. ليصل الإجمالي إلى 117 حقلًا مميزًا موزّعة على أنواع الصفحات.
هذا الجدول مصمّم كي تحفظه في المفضلة. معرفة مخطط بياناتك قبل البرمجة توفّر عليك ساعات من التجربة والخطأ في البحث عن المحددات.
حقول صفحة نتائج البحث
هذه هي الحقول الخفيفة المتاحة على بطاقات الإعلانات، ويمكن استخراجها غالبًا دون الحاجة إلى تصيير JavaScript كاملًا:
| الحقل | نوع البيانات | ملاحظات |
|---|---|---|
| معرّف العقار | رقم | عدد صحيح داخلي لدى Redfin، يُستخرج من /home/{id} في الرابط |
| سعر الطلب | رقم | |
| العنوان الكامل | نص | |
| غرف النوم / الحمامات / المساحة بالقدم المربع | رقم | ثلاث قيم متتالية |
| نوع العقار | اختيار مفرد | منزل مستقل، شقة، تاون هاوس، متعدد الوحدات |
| الحالة | نص | نشط، قيد الانتظار، مشروط |
| أيام العرض في السوق | رقم | |
| مؤشر تخفيض السعر | رقم | الفرق عن السعر الأصلي |
| الصورة الرئيسية | رابط صورة | صورة واحدة لكل بطاقة |
| شارة Hot Home | قيمة منطقية | |
| تاريخ/وقت البيت المفتوح | نص | |
| نسبة الوساطة العقارية | نص |
حقول صفحة تفاصيل العقار
صفحة التفاصيل هي حيث يكمن العمق الحقيقي. وكثير من هذه الحقول يتطلب تصيير JavaScript أو استخدام Stingray API:
| الحقل | نوع البيانات | ملاحظات |
|---|---|---|
| تقدير Redfin (معروض في السوق) | رقم | عبر /stingray/api/home/details/avm |
| تقدير Redfin (خارج السوق) | رقم | عبر /stingray/api/home/details/owner-estimate؛ متوسط خطأ 7.52% |
| سنة البناء / التجديد | رقم | |
| مساحة الأرض | رقم | |
| رسوم اتحاد الملاك (HOA) | رقم | شهريًا، إن وُجدت |
| الضريبة العقارية (سنويًا) | رقم | |
| القيمة الضريبية المقدَّرة | رقم | |
| جدول تاريخ البيع | جدول | السعر، التاريخ، نوع الحدث |
| وصف العقار | نص | الفقرة التسويقية |
| روابط الصور (العارض) | روابط صور | أكثر من 20 لكل إعلان |
| اسم وكيل الإعلان وهاتفه وبريده | نص / هاتف / بريد | الهاتف مخفي غالبًا |
| تقييمات المدارس (ابتدائي/متوسط/ثانوي) | رقم | إضافةً إلى اسم المنطقة التعليمية |
| درجات المشي / النقل / الدراجات | رقم | |
| درجات المخاطر المناخية | رقم | الفيضان، الحريق، الحرارة، الرياح |
| منازل مشابهة نشطة / مباعة / قريبة | روابط | بيانات العارض |
| المواقف والمرآب والتدفئة والتبريد | نص | مجموعات المرافق |
حقول ملف الوكيل
| الحقل | نوع البيانات | ملاحظات |
|---|---|---|
| اسم الوكيل وصورته ووساطته ونبذته | نص / صورة | |
| الهاتف، نموذج التواصل | هاتف / نص | يظهر بالنقر |
| عدد الإعلانات النشطة | رقم | |
| المبيعات خلال آخر 12 شهرًا / إجمالي الحجم | رقم | |
| متوسط نسبة سعر الطلب إلى سعر البيع | رقم | |
| تقييم النجوم / عدد المراجعات | رقم | |
| سنوات الخبرة / رقم الترخيص | نص / رقم |
عندما تستخدم ميزة اقتراح الحقول بالذكاء الاصطناعي (AI Suggest Fields) في Thunderbit على صفحة Redfin، فإنها تكتشف معظم هذه الأعمدة تلقائيًا وتعيّن لها أنواع البيانات الصحيحة، دون الحاجة إلى ربط محددات CSS يدويًا. سنعود إلى ذلك لاحقًا.
تفكيك دفاعات Redfin ضد الروبوتات (وليس مجرد «استخدم بروكسي»)
هنا أريد أن أزرع راية، لأن معظم الشروحات تمرّ مرور الكرام على مشكلة الحجب وتقفز مباشرةً إلى «اشترِ بروكسيات من راعينا». هذا غير مفيد. إذا لم تفهم ماذا يفعل Redfin لكشف أدوات التجريف، فستستنزف رصيد البروكسيات وتظل محجوبًا. يقيّم ScrapeOps صعوبة مكافحة الروبوتات في Redfin بـ 7.5 من 10، بينما يصنّفها Scraperly بأنها متوسطة (3/5) — «أقل عدوانية من جدار الحماية المؤسسي لدى Zillow، وتعتمد على تحديد معدل مخصص وتحديات JavaScript».
يشغّل Redfin منظومة متعددة الطبقات: Cloudflare على الحافة (تحدي JS، وTurnstile، وبصمة TLS/JA3) إضافةً إلى محدِّد معدل خاص بـ Redfin على مستوى التطبيق. ولا يوجد توجيه Crawl-delay في ملف robots.txt لديهم لأن التطبيق يتم على مستوى جدار حماية تطبيقات الويب.
لماذا يفشل requests + BeautifulSoup البسيط مع Redfin
إذا أطلقت طلب requests.get() أساسيًا إلى صفحة عقار في Redfin بالترويسات الافتراضية، فإليك ما يحدث عادةً:
- HTTP 403 — لم يُحلّ تحدي JS الخاص بـ Cloudflare، فتحصل على صفحة التحدي بدلًا من الإعلان.
- صفحة تحدٍّ اعتراضية — يحتوي جسم HTML على أداة Turnstile من Cloudflare، لا على بيانات العقار.
- HTTP 200 مع HTML جزئي — تحصل على هيكل يتضمّن كتلة JSON مضمّنة كبيرة تحت
root.__reactServerState.InitialContext، لكن دون بطاقات بحث مصيَّرة مسبقًا، ودون تاريخ الأسعار، ودون تقييمات المدارس.
يستخدم Redfin إطار React SSR الخاص به (وليس Next.js)، ومفتاح الترطيب (hydration) خاص بـ Redfin: root.__reactServerState.InitialContext مع بيانات الإعلانات المتداخلة تحت ReactServerAgent.cache.dataCache. وهذا ليس __NEXT_DATA__ ولا window.__INITIAL_STATE__.
وما السبب الأكثر شيوعًا لأخطاء 403 الصامتة؟ غياب ترويسات Sec-Fetch-*. فـ Redfin/Cloudflare يتحققان صراحةً من Sec-Fetch-Site وSec-Fetch-Mode وSec-Fetch-Dest وSec-Fetch-User. وإذا غابت، تُوسم فورًا.
دليل المواجهة: التأخيرات والترويسات والبروكسيات والجلسات
إليك التفصيل الكامل، دفاعًا بدفاع، مع إجراءات مضادة محددة لكل منها:
| دفاع Redfin | ماذا يفعل | إشارة الكشف | استراتيجية المواجهة |
|---|---|---|---|
| تحدي JS من Cloudflare | صفحة اعتراضية تصدر كوكي cf_clearance | 403 + جسم HTML من Cloudflare | curl_cffi مع impersonate="chrome120"؛ تسخين الجلسة عبر الصفحة الرئيسية؛ بروكسي سكني أمريكي |
| Cloudflare Turnstile | كابتشا تفاعلية للجلسات عالية المخاطر | 403 + أداة Turnstile | متصفح بلا واجهة مع وضع التخفي + بروكسي سكني |
| خطأ Cloudflare 1020 (حظر ASN) | يحجب عناوين IP/ASN الموسومة على مستوى WAF | جسم 403 يحمل "Error 1020 Access Denied" | التبديل إلى بروكسي سكني/جوّال؛ لا تستخدم ASN لمراكز البيانات أبدًا |
| بصمة TLS/JA3 | تكشف حِزم TLS غير الخاصة بالمتصفحات | 403 صامت حتى مع ترويسات مثالية | انتحال curl_cffi أو متصفح حقيقي |
| بصمة HTTP/2 | تفحص إعدادات HTTP/2 وترتيب HPACK | حجب صامت | curl_cffi يتحدث HTTP/2 مثل Chrome |
| التحقق من الترويسات (UA، Sec-Fetch-*) | مجموعة ترويسات متسقة مع المتصفح | 403 من أول طلب | مجموعة ترويسات Chrome كاملة تشمل Sec-Fetch-Site/Mode/Dest/User وReferer واقعي |
| استمرارية الكوكيز/الجلسة | تتبّع cf_clearance وRF_BROWSER_ID | تحديات عند الدخول البارد إلى روابط عميقة | جلسة دائمة؛ سخّن عبر الصفحة الرئيسية أولًا |
| تحديد المعدل على مستوى التطبيق | محدِّد طلبات لكل IP | 429 | تأخير 2–5 ثوانٍ مع تشويش عشوائي؛ تراجع أُسّي |
| سمعة عناوين مراكز البيانات | تحجب ASN معروفة لمراكز البيانات | 1020/403 فوري | بروكسيات سكنية أو جوّالة أمريكية فقط |
| كشف التزامن | طلبات متوازية متعددة من IP واحد | تصعيد مفاجئ إلى Turnstile | ما لا يزيد عن طلبين متزامنين لكل IP |
عتبات عملية من اختبارات المجتمع:
- الإيقاع الآمن: طلب واحد كل 2–3 ثوانٍ لكل IP
- تجاوز 20–30 طلبًا في الدقيقة بشكل مستمر من عنوان IP واحد لمركز بيانات يُطلق تحديًا خلال دقائق
- تُرفع حدود المعدل المرنة خلال 5–15 دقيقة إذا توقفت حركة الطلبات
- قد يستمر حظر عناوين مراكز البيانات (AWS، GCP، Azure، OVH) من ساعات إلى أيام
مكتبة requests القياسية في Python (urllib3 + OpenSSL) تنتج بصمة JA3 لا تطابق أي متصفح، وتُحجب صامتة حتى مع ترويسات مثالية. والحل المعتمد في المجال هو curl_cffi مع impersonate="chrome120"، الذي يتحدث TLS + HTTP/2 بدقة مطابقة لـ Chrome.
ثلاث طرق لتجريف Redfin باستخدام Python (وأيها تختار)

لم أجد شرحًا منافسًا واحدًا يقارن المقاربات الثلاث جنبًا إلى جنب. إليك مصفوفة القرار:
| المعيار | تحليل HTML (BS4 + Selenium) | واجهة Stingray المخفية | Thunderbit (بلا أكواد) |
|---|---|---|---|
| صعوبة الإعداد | متوسطة (بيئة Python + مشغّل المتصفح) | مرتفعة (هندسة عكسية لنقاط النهاية) | منخفضة (تثبيت إضافة Chrome) |
| خطر مكافحة الروبوتات | مرتفع (طلبات DOM هي الأكثر وضوحًا) | متوسط (الطلبات الشبيهة بالـ API تبدو أنظف) | الأدنى (يستخدم جلسة متصفحك الحقيقية) |
| جودة بنية البيانات | متوسطة (HTML غير منظّم ← تحليل يدوي) | ممتازة (JSON منظّم مسبقًا) | عالية (الذكاء الاصطناعي يكتشف الحقول والأنواع تلقائيًا) |
| عبء الصيانة | مرتفع — تغيير واحد في التخطيط يكسر المحددات | متوسط — قد تتغير نقاط النهاية دون إشعار | الأدنى — الذكاء الاصطناعي يتكيّف مع تغيّر التخطيط |
| القابلية للتوسّع | منخفضة إلى متوسطة (مئات الصفحات مع بروكسيات) | متوسطة إلى عالية (آلاف، بطلبات أنظف) | متوسطة (50 صفحة لكل دفعة عبر التجريف السحابي) |
| الأنسب لـ | المطورين الراغبين في تحكّم كامل | المطورين الذين يحتاجون JSON نظيفًا | غير المبرمجين، المشاريع السريعة، البيانات المستمرة دون موارد تطوير |
يستحق جانب الصيانة تأكيدًا خاصًا. فقد أطلق Redfin جيلين من DOM البطاقات: القديم (homecardV2Price) والحالي (span.bp-Homecard__Price--value). ويُظهر سجل مشكلات GitHub لدى المجتمع أن محددات CSS تنكسر كل 6 إلى 12 شهرًا تقريبًا. وعندما يحدث ذلك، ينهار سكربت BeautifulSoup بين ليلة وضحاها. أما كاشف الحقول القائم على الذكاء الاصطناعي، فيتكيّف.
قبل أن تبدأ
- الصعوبة: متوسطة (المقاربتان 1 و2)، مبتدئة (المقاربة 3)
- الوقت المطلوب: نحو 30 دقيقة للمقاربة 1 أو 2؛ ونحو 5 دقائق للمقاربة 3
- ما ستحتاجه:
- Python 3.8 أو أحدث مع pip (المقاربتان 1 و2)
- متصفح Chrome (جميع المقاربات)
- إضافة Thunderbit لمتصفح Chrome (المقاربة 3)
- بروكسيات سكنية أمريكية للتجريف واسع النطاق (المقاربتان 1 و2)
استخرج بيانات Redfin بالذكاء الاصطناعي Get Started Free
المقاربة 1: تجريف Redfin بلغة Python عبر تحليل HTML (BeautifulSoup + Selenium)
هذا هو مسار «التحكّم الكامل». أنت من يكتب المحددات، وأنت من يدير المتصفح، وأنت من يعالج الأخطاء.
إنها المقاربة الأكثر إفادة تعليميًا. وهي أيضًا الأكثر هشاشة.
الخطوة 1: إعداد بيئة Python
أنشئ بيئة افتراضية وثبّت المكتبات المطلوبة:
python -m venv redfin-scraper
source redfin-scraper/bin/activate # على Windows: redfin-scraper\Scripts\activate
pip install requests beautifulsoup4 selenium webdriver-manager pandas curl_cffi
مكتبة curl_cffi أساسية هنا، فهي ما يتيح لطلبات HTTP لديك انتحال بصمة TLS الخاصة بمتصفح Chrome حقيقي، بدلًا من بصمة requests القياسية في Python التي تحجبها Cloudflare من أول نظرة.
الخطوة 2: ضبط ترويسات المتصفح والجلسة
هنا يفشل معظم المبتدئين. أنت بحاجة إلى مجموعة ترويسات Chrome الكاملة، بما فيها ترويسات Sec-Fetch-* التي يتحقق منها Redfin/Cloudflare صراحةً:
from curl_cffi import requests as curl_requests
HEADERS = {
"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) "
"AppleWebKit/537.36 (KHTML, like Gecko) "
"Chrome/120.0.0.0 Safari/537.36",
"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
"Accept-Language": "en-US,en;q=0.9",
"Accept-Encoding": "gzip, deflate, br",
"Sec-Fetch-Site": "none",
"Sec-Fetch-Mode": "navigate",
"Sec-Fetch-Dest": "document",
"Sec-Fetch-User": "?1",
}
session = curl_requests.Session(impersonate="chrome120")
session.headers.update(HEADERS)
# تسخين الجلسة — جمع كوكيز cf_clearance و RF_BROWSER_ID
session.get("https://www.redfin.com/")
خطوة تسخين الجلسة حاسمة، فالدخول البارد إلى رابط عقار عميق (دون كوكيز سابقة ودون Referer) يخفّض تقييمك لدى Cloudflare.
ابدأ دائمًا من الصفحة الرئيسية.
الخطوة 3: تجريف نتائج البحث في Redfin
بعد تسخين جلستك، يمكنك جلب صفحة بحث لمدينة ما وتحليل بطاقات الإعلانات. المحددات من الجيل الحالي (2024–2026):
import time
import random
from bs4 import BeautifulSoup
base_url = "https://www.redfin.com/city/17151/CA/San-Francisco"
listings = []
for page_num in range(1, 6): # الصفحات من 1 إلى 5
url = f"{base_url}/page-{page_num}" if page_num > 1 else base_url
resp = session.get(url)
if resp.status_code != 200:
print(f"Blocked on page {page_num}: HTTP {resp.status_code}")
break
soup = BeautifulSoup(resp.text, "html.parser")
cards = soup.select("[data-rf-test-id='property-card'], a.bp-Homecard")
for card in cards:
price_el = card.select_one("span.bp-Homecard__Price--value")
addr_el = card.select_one("a.bp-Homecard__Address")
stats = card.select("span.bp-Homecard__LockedStat--value")
listing = {
"price": price_el.text.strip() if price_el else None,
"address": addr_el.text.strip() if addr_el else None,
"beds": stats[0].text.strip() if len(stats) > 0 else None,
"baths": stats[1].text.strip() if len(stats) > 1 else None,
"sqft": stats[2].text.strip() if len(stats) > 2 else None,
"url": "https://www.redfin.com" + addr_el["href"] if addr_el else None,
}
listings.append(listing)
# تأخير عشوائي بين 2 و5 ثوانٍ
time.sleep(random.uniform(2, 5))
print(f"Scraped {len(listings)} listings")
من المفترض أن ترى قائمة متنامية من القواميس، يحتوي كل منها على سعر إعلان في سان فرانسيسكو وعنوانه وعدد الغرف/الحمامات/المساحة ورابط التفاصيل. وإذا حصلت على 0 بطاقة، فتحقّق من رمز حالة HTTP: الرمز 403 يعني أن Cloudflare أمسكت بك، وغالبًا ستحتاج إلى بروكسيات سكنية.
الخطوة 4: تجريف صفحات تفاصيل العقارات الفردية
نتائج البحث تعطيك الأساسيات. أما صفحات التفاصيل فتعطيك تقدير Redfin، وسنة البناء، ورسوم اتحاد الملاك، وتاريخ البيع، ومعلومات الوكيل، والصور. وهذه الصفحات تتطلب تصيير JavaScript، لذا انتقل إلى Selenium:
from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from webdriver_manager.chrome import ChromeDriverManager
from selenium.webdriver.common.by import By
import time
options = webdriver.ChromeOptions()
options.add_argument("--headless=new")
options.add_argument("--disable-blink-features=AutomationControlled")
options.add_argument("user-agent=Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) "
"AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36")
driver = webdriver.Chrome(service=Service(ChromeDriverManager().install()), options=options)
for listing in listings[:10]: # إثراء أول 10 إعلانات
driver.get(listing["url"])
time.sleep(random.uniform(3, 6)) # انتظار تصيير JavaScript
try:
estimate_el = driver.find_element(By.CSS_SELECTOR, "[data-rf-test-name='avmLdpPrice']")
listing["redfin_estimate"] = estimate_el.text.strip()
except:
listing["redfin_estimate"] = None
try:
year_built = driver.find_element(By.XPATH, "//span[contains(text(),'Year Built')]/following-sibling::span")
listing["year_built"] = year_built.text.strip()
except:
listing["year_built"] = None
driver.quit()
بعد هذه الخطوة، ينبغي أن تكون أول 10 إعلانات لديك مُثراة بقيم تقدير Redfin وبيانات سنة البناء. ومحددات XPath أكثر مرونة من CSS مع حقول المرافق المتداخلة هذه، لكنها تبقى هشّة: أي إعادة هيكلة لـ DOM ستكسرها.
الخطوة 5: التعامل مع الحجب والأخطاء
طبّق منطق إعادة المحاولة مع تراجع أُسّي:
import time
def fetch_with_retry(session, url, max_retries=3):
for attempt in range(max_retries):
resp = session.get(url)
if resp.status_code == 200:
return resp
elif resp.status_code in (403, 429, 503):
wait = (2 ** attempt) + random.uniform(1, 3)
print(f"Blocked ({resp.status_code}). Retrying in {wait:.1f}s...")
time.sleep(wait)
else:
print(f"Unexpected status: {resp.status_code}")
break
return None
علامات تدلّ على أنك حُجبت: رمز HTTP 403 مع HTML من Cloudflare في الجسم، أو HTTP 429 (تحديد معدل صريح)، أو جسم استجابة فارغ، أو ظهور "Error 1020 Access Denied" في محتوى الصفحة. وإذا كنت تواجه هذه العلامات باستمرار، فقد حان وقت إضافة بروكسيات سكنية أو التحوّل إلى مقاربة الـ API.
المقاربة 2: تجريف Redfin بلغة Python عبر واجهة Stingray المخفية
هذه مقاربتي المفضّلة. فواجهة Redfin الأمامية تتحدث إلى واجهة JSON داخلية على /stingray/api/home/details/*، وتعود الاستجابات على شكل JSON نظيف ومحدد الأنواع، دون أي حاجة إلى تحليل HTML.
كيف تكتشف نقاط النهاية المخفية في Redfin
افتح أدوات مطوّري Chrome ← تبويب Network ← فلترة حسب Fetch/XHR ← ثم انتقل إلى أي صفحة عقار في Redfin. سترى طلبات إلى نقاط نهاية مثل:
api/home/details/initialInfo— يحوّل الرابط إلى propertyId وlistingIdapi/home/details/aboveTheFold— السعر، الغرف، الحمامات، المساحة، الصور، الحالة، الوكيل، رقم MLSapi/home/details/belowTheFold— المرافق، رسوم اتحاد الملاك، الضرائب، المواقف، سنة البناء، الأرض، التاريخapi/home/details/avm— تقدير Redfin للعقارات المعروضة في السوقapi/home/details/owner-estimate— تقدير Redfin للعقارات خارج السوقapi/home/details/descriptiveParagraph— الوصف التسويقي
أما بالنسبة لصفحات الإيجار، فيُستخرج rentalId (وهو UUID مكوّن من 36 حرفًا) من رابط وسم <meta property="og:image">.
تجريف بيانات العقارات عبر Stingray API
هناك خصوصية بالغة الأهمية: استجابات Stingray بصيغة JSON تبدأ بالسلسلة الحرفية {}&& كإجراء لمكافحة تزوير الطلبات عبر المواقع (CSRF). ويجب حذفها قبل التحليل:
import json
from curl_cffi import requests as curl_requests
session = curl_requests.Session(impersonate="chrome120")
session.headers.update(HEADERS)
# تسخين الجلسة
session.get("https://www.redfin.com/")
# جلب صفحة العقار للحصول على الكوكيز ومعرّف العقار
property_url = "https://www.redfin.com/CA/San-Francisco/123-Main-St-94102/home/12345678"
page_resp = session.get(property_url)
# الآن اطلب Stingray API
api_url = "https://www.redfin.com/stingray/api/home/details/aboveTheFold?propertyId=12345678"
api_resp = session.get(api_url, headers={"Referer": property_url})
# حذف بادئة مكافحة CSRF
payload = json.loads(api_resp.text.replace("{}&&", "", 1))
# استخراج البيانات المنظّمة
listing_data = payload.get("payload", {})
print(json.dumps(listing_data, indent=2))
تتضمن الاستجابة حقولًا محددة الأنواع: السعر كعدد صحيح، والغرف والحمامات كأرقام، وروابط الصور كمصفوفات، ومعلومات الوكيل ككائنات متداخلة. لا تحليل بـ BeautifulSoup، ولا محددات CSS، ولا تخمين.
مزايا وقيود مقاربة الواجهة المخفية
المزايا:
- JSON منظّم مسبقًا — أنظف بكثير من تحليل HTML
- أسرع لكل طلب (حمولات أصغر، ولا عبء تصيير)
- خطر حجب أقل (الطلبات الشبيهة بالـ API مع ترويسات سليمة تبدو أكثر طبيعية)
القيود:
- قد تتغير نقاط النهاية دون إشعار — ولا يوجد توثيق رسمي
- يمنع ملف
robots.txtصراحةً الوصول إلى/stingray/لوكيل المستخدم العام - يتطلب هندسة عكسية لاكتشاف نقاط نهاية جديدة
- ما زال يحتاج إلى تسخين الجلسة وترويسات سليمة لتفادي Cloudflare
البديل بلا أكواد: تجريف Redfin باستخدام Thunderbit
إذا كنت تحتاج بيانات Redfin ولا ترغب في صيانة سكربتات Python، أو أردت ببساطة نتائج خلال خمس دقائق، فابدأ من هنا. لقد بنينا Thunderbit لهذا الغرض تمامًا: استخراج بيانات منظّمة من أي موقع، دون أي كود.
الخطوة 1: ثبّت Thunderbit وانتقل إلى Redfin
ثبّت إضافة Thunderbit لمتصفح Chrome من متجر Chrome الإلكتروني. افتح Redfin وانتقل إلى صفحة نتائج بحث، مثل منازل سان فرانسيسكو المعروضة للبيع.
الخطوة 2: انقر على «AI Suggest Fields»
انقر على أيقونة Thunderbit في شريط أدوات متصفحك، ثم انقر على «AI Suggest Fields». يقرأ الذكاء الاصطناعي صفحة Redfin ويقترح تلقائيًا أعمدة مثل «العنوان» و«السعر» و«غرف النوم» و«الحمامات» و«المساحة بالقدم المربع» و«نوع العقار» و«صورة الإعلان»، مع تعيين أنواع البيانات الصحيحة تلقائيًا.
ويمكنك حذف الأعمدة التي لا تحتاجها، أو إضافة أعمدة مخصصة بالنقر على «+ Add Column» ووصف ما تريده بلغة طبيعية بسيطة (مثل «اسم وكيل الإعلان» أو «أيام العرض في السوق»).
من المفترض أن ترى معاينة لجدول يحتوي على الأعمدة التي ضبطتها، جاهزًا للتعبئة.
الخطوة 3: انقر على «Scrape» وشاهد البيانات تتدفق
انقر على زر «Scrape». يعالج Thunderbit الإعلانات الظاهرة ويملأ جدولك. وفي حالة النتائج المقسّمة إلى صفحات، يتعامل مع التنقّل بين الصفحات تلقائيًا، دون الحاجة إلى أي منطق حلقات.
في اختباراتي، امتلأ جدول من 50 صفًا في نحو 45 ثانية. بيانات منظّمة، جاهزة للتصدير.
كيف يتعامل Thunderbit مع حماية Redfin ضد الروبوتات
بما أن Thunderbit يعمل داخل متصفحك أنت، فإنه يرث كوكيز Redfin الحالية لديك، وجلستك، وبصمة متصفحك. وبالنسبة لـ Cloudflare، يبدو الأمر وكأن مستخدمًا عاديًا يتصفح Redfin — لأنه من الناحية التقنية كذلك فعلًا. لا متصفح بلا واجهة، ولا عنوان IP لمركز بيانات، ولا بصمة TLS غير متطابقة. وبالنسبة للصفحات المتاحة للعموم، يستطيع وضع التجريف السحابي في Thunderbit معالجة 50 صفحة في وقت واحد.
هذا وضع مختلف جذريًا عن إطلاق طلبات requests من سكربت Python على خادم.
جلسة متصفحك موثوقة بالفعل.
تجريف الصفحات الفرعية في Redfin باستخدام Thunderbit
بعد تجريف نتائج البحث، انقر على «Scrape Subpages» ليقوم الذكاء الاصطناعي بزيارة رابط تفاصيل كل عقار وإثراء جدولك بحقول إضافية: تقدير Redfin، وسنة البناء، ورسوم اتحاد الملاك، ومعلومات الوكيل، وصور العقار، وتاريخ البيع.
وهذا يعادل حلقة Selenium المكوّنة من 40 سطرًا في المقاربة 1، باستثناء أنه يستغرق نقرة واحدة وصيانة صفرية.
وعندما يغيّر Redfin هيكل DOM من homecardV2Price إلى span.bp-Homecard__Price--value، يتكيّف الذكاء الاصطناعي. أما محددات Python لديك، فلا.
استخرج الصفحات الفرعية لـ Redfin بالذكاء الاصطناعي Get Started Free
أبعد من CSV: تصدير بيانات Redfin إلى Google Sheets وAirtable وNotion
تتوقف معظم الشروحات عند df.to_csv(). وهذا مقبول لتحليل لمرة واحدة. لكن إذا كنت ضمن فريق عقاري، فأنت بحاجة إلى بيانات تعاونية وحيّة، لا ملفات ثابتة تتراكم عليها الأتربة على سطح مكتب أحدهم.
التصدير باستخدام Python (gspread + واجهة Airtable)
Google Sheets عبر gspread:
import gspread
import pandas as pd
from gspread_dataframe import set_with_dataframe
df = pd.DataFrame(listings)
gc = gspread.service_account(filename="service_account.json")
sh = gc.open("Redfin Listings")
ws = sh.worksheet("Sheet1")
ws.clear()
set_with_dataframe(ws, df, include_index=False, resize=True)
# عرض صور العقارات داخل الخلايا عبر دالة IMAGE()
image_col = df.columns.get_loc("image_url") + 1
for row_idx, url in enumerate(df["image_url"], start=2):
ws.update_cell(row_idx, image_col, f'=IMAGE("{url}")')
انتبه: لدى Sheets حد صارم يبلغ 10 ملايين خلية لكل جدول بيانات، وتسمح الواجهة بـ 300 طلب قراءة و300 طلب كتابة في الدقيقة لكل مشروع. استخدم ws.batch_update() بدلًا من الحلقات على مستوى الخلية لأي شيء يتجاوز بضع عشرات من الصفوف.
Airtable عبر pyairtable:
تغيير جوهري في 2024: أوقفت Airtable العمل بمفاتيح الواجهة القديمة في 1 فبراير 2024. عليك الآن استخدام رموز الوصول الشخصية (PATs)؛ وأي شرح ما زال يعرض api_key=... فهو غير صالح.
from pyairtable import Api
api = Api("patXXXXXXXXXXXXXX.yyyyyyyyyyyyyyyyyyyy")
table = api.table("appBaseId123", "Redfin Listings")
records = [
{
"Address": row["address"],
"Price": row["price"],
"Beds": row["beds"],
"Photo": [{"url": row["image_url"]}], # Airtable يجلبها ويعيد استضافتها
}
for row in listings
]
created = table.batch_create(records, typecast=True)
حد المعدل في Airtable هو 5 طلبات في الثانية لكل قاعدة، مع إيقاف لمدة 30 ثانية عند المخالفة. ويقبل حقل المرفقات حمولات بصيغة [{"url": ...}]؛ إذ تجلب خوادم Airtable الرابط، وتعيد استضافته على شبكة التوزيع الخاصة بها، وتولّد الصور المصغّرة تلقائيًا.
التصدير باستخدام Thunderbit (نقرة واحدة إلى Sheets وAirtable وNotion)
يوفّر Thunderbit تصديرًا أصليًا بنقرة واحدة إلى Google Sheets وAirtable وNotion، وإليك الجزء الذي أفخر به حقًا: تُرفع صور العقارات وتُعرض كصور مضمّنة داخل Notion وAirtable. لا حيل بدالة =IMAGE()، ولا روابط CDN مكسورة. تنقر على «Export to Airtable»، ويحصل فريقك على قاعدة بيانات عقارية بصرية بصور مصغّرة يمكنهم تصفّحها من هواتفهم.
بالنسبة للفرق العقارية التي تفرز الإعلانات بصريًا، هذا هو الفرق بين أداة مفيدة وكومة من صفوف CSV.
هل تجريف Redfin قانوني؟ ماذا تقول شروط الاستخدام وrobots.txt والسوابق القضائية
لست محاميًا، وهذا ليس استشارة قانونية. لكن بعد سنوات في مجال استخراج البيانات، يمكنني أن أقول: «هل هذا قانوني؟» هو السؤال الذي يطرحه الجميع وتتهرب منه معظم الشروحات.
ملف robots.txt لدى Redfin
ملف robots.txt لدى Redfin مفصّل. وأبرز نقاطه:
- روبوتات محظورة كليًا:
peer39_crawler/1.0وAmazonAdBotوFireCrawlAgent— إذ يذكر Redfin بالاسم خدمة التجريف الشهيرة في عصر نماذج اللغة الكبيرة - أبرز ما يمنعه
User-agent: *العام:/stingray/(كامل مساحة الأسماء الخاصة بالواجهة الداخلية)، و/myredfin/، و/api/v1/rentals/، و/api/v1/properties/، و/owner-estimate/ - لا يوجد توجيه
Crawl-delay:لأي وكيل مستخدم - أكثر من 50 خريطة موقع معلنة — وخرائط المواقع هي أنظف طريقة لتعداد الروابط وأقلها احتكاكًا بجدار الحماية
شروط استخدام Redfin
ينص البند 2.3.5 على: «لا يجوز لك الزحف إلى الخدمات أو الاستعلام عنها بشكل آلي لأي غرض أو بأي وسيلة... ما لم تكن قد حصلت على إذن خطي صريح مسبق.»
هذه اتفاقية من نوع browsewrap، أي أن القبول يتم بمجرد الاستمرار في الاستخدام، لا بالنقر على موافقة. وقد كانت المحاكم الأمريكية تاريخيًا متشككة في إنفاذ اتفاقيات browsewrap بحق مستخدمين لم يكن لديهم علم فعلي بها (انظر قضية Nguyen v. Barnes & Noble، الدائرة التاسعة، 2014).
سوابق قضائية ذات صلة (بإيجاز)
- Van Buren v. United States (المحكمة العليا، 2021): بند «تجاوز الوصول المصرّح به» في قانون CFAA يخضع لاختبار «البوابة مفتوحة أم مغلقة». واستخدام باب مفتوح لغرض غير مرحّب به ليس اختراقًا فيدراليًا.
- hiQ Labs v. LinkedIn (الدائرة التاسعة، 2022): تجريف البيانات المتاحة للعموم ليس انتهاكًا لقانون CFAA. لكن hiQ دفعت في النهاية 500,000 دولار في تسوية على أساس الإخلال بالعقد، لأنها كانت تملك حسابات مسجّلة على LinkedIn ونقرت على «أوافق».
- Meta Platforms v. Bright Data (المحكمة الفيدرالية لشمال كاليفورنيا، يناير 2024): منحت المحكمة حكمًا مستعجلًا لصالح Bright Data — فالتجريف دون تسجيل دخول للبيانات العامة لا يجعل Bright Data «مستخدمًا» ملزمًا بشروط استخدام Meta.
- X Corp. v. Bright Data (المحكمة الفيدرالية لشمال كاليفورنيا، مايو 2024): رفض القاضي Alsup دعاوى X، معتبرًا أن دعاوى قانون الولاية التي تحاول التحكم في نسخ المحتوى العام يجبّها قانون حقوق النشر الفيدرالي.
إرشادات عملية
- جرّف فقط البيانات المتاحة للعموم، ولا تسجّل حسابًا ثم تجرّف (فذلك يعرّضك لالتزام تعاقدي من نوع clickwrap)
- احترم حدود المعدل — فالأحجام العدوانية تدعم دعاوى التعدي على الممتلكات المنقولة
- لا تعِد نشر البيانات الخام أو الصور على نطاق واسع — فدعوى CoStar ضد Zillow (المرفوعة في يوليو 2025، بتعويضات محتملة تتجاوز مليار دولار) تذكير بأن حقوق نشر الصور مسألة جدية
- مقاربة Thunderbit القائمة على المتصفح — أي العمل داخل جلستك المصادَق عليها — أقرب إلى «تصفّح يدوي بسرعة الآلة» منها إلى روبوت بلا واجهة يعمل من مركز بيانات، وهذا هو الوضع الأكثر قابلية للدفاع عنه بعد الواجهات المرخّصة
نصائح وأخطاء شائعة
بعض الدروس المكتسبة بشق الأنفس من بناء أدوات الاستخراج ومتابعة آلاف المستخدمين وهم يجرّفون مواقع العقارات:
- سخّن جلستك دائمًا. ادخل إلى
redfin.com/قبل أي رابط عميق. فالدخول البارد إلى الروابط العميقة هو المحرّك الأول لتحديات Cloudflare. - دوّر نصوص User-Agent بشكل واقعي. لا تستخدم واحدًا فقط، بل دوّر بين 5 إلى 10 نصوص حديثة من Chrome/Firefox. لكن لا تبالغ في التدوير (تغيير UA مع كل طلب يبدو مريبًا).
- أزل التكرار حسب معرّف العقار. يتداخل ترقيم صفحات Redfin أحيانًا. استخرج
/home/{id}من رابط كل إعلان وأزل التكرار قبل الإثراء. - تجنّب التجريف في ساعات الذروة إن أمكن. حسب تجربتي، تشهد ساعات الليل المتأخرة والصباح الباكر بتوقيت الولايات المتحدة تدقيقًا أقل من جدار الحماية.
- إذا واجهت 429، تراجع أُسّيًا. لا تعِد المحاولة فورًا، فهكذا تتصاعد من تحديد معدل مرن إلى حظر IP صارم.
- للمشاريع واسعة النطاق (أكثر من 1000 صفحة)، خصّص ميزانية لبروكسيات سكنية. فعناوين مراكز البيانات (AWS، GCP، Azure، OVH) مدرجة في القوائم السوداء لنظام سمعة ASN لدى Cloudflare. وستواجه الخطأ 1020 على الفور تقريبًا.
اختيار الطريقة المناسبة لتجريف Redfin
إذًا، أي مقاربة ينبغي أن تختار؟ يعتمد ذلك على من أنت وما تحتاجه.
تحليل HTML (BeautifulSoup + Selenium): الأفضل للمطورين الذين يريدون تحكمًا كاملًا، ولا يمانعون صيانة محددات CSS، ولا يزعجهم إعادة البناء عندما يغيّر Redfin هيكل DOM. توقّع أن تعود إلى كودك كل 6 إلى 12 شهرًا.
واجهة Stingray المخفية: الأفضل للمطورين الذين يحتاجون JSON نظيفًا ومنظّمًا، ويستطيعون التعامل مع الهندسة العكسية لنقاط نهاية غير موثّقة. صيانتها أقل من تحليل HTML، لكن نقاط النهاية قد تتغير دون إشعار. وتذكّر أن /stingray/ ممنوع صراحةً في ملف robots.txt.
Thunderbit (بلا أكواد): الأفضل لغير المطورين، وللمشاريع السريعة، وللفرق التي تحتاج بيانات Redfin بشكل مستمر دون موارد تطوير. فالذكاء الاصطناعي يتكيّف مع تغيّرات التخطيط، وتجريف الصفحات الفرعية يثري البيانات بنقرة واحدة، والتصدير إلى Google Sheets أو Airtable أو Notion مدمج أصلًا. وإذا كنت فريقًا عقاريًا يحتاج قاعدة بيانات عقارية حيّة، لا ملف CSV لمرة واحدة، فهذا هو المسار الأقل مقاومة.
وأيًّا كان المسار الذي تسلكه: افهم دفاعات Redfin ضد الروبوتات قبل أن تبدأ، واعرف ما الحقول التي تحتاجها، واختر صيغة تصدير تناسب سير عمل فريقك، وابقَ على الجانب الصحيح من الإرشادات القانونية.
مستعد لتجربة المسار بلا أكواد؟ الخطة المجانية من Thunderbit تتيح لك تجربة تجريف Redfin ورؤية النتائج خلال دقائق. أما بالنسبة لمقاربات Python، فالمقتطفات البرمجية أعلاه نقطة انطلاق عملية، ولا ينقصها سوى البروكسيات والصبر.
جرّب Thunderbit للحصول على بيانات Redfin محدَّثة باستمرار
الأسئلة الشائعة
هل لدى Redfin واجهة برمجية عامة؟
لا. لا يقدّم Redfin واجهة برمجية عامة رسمية. أما واجهة Stingray المخفية (/stingray/api/home/details/*) فتعيد JSON منظّمًا وتستخدمها واجهة Redfin الأمامية نفسها، لكنها غير رسمية وغير موثّقة وقابلة للتغيير دون إشعار وممنوعة صراحةً في ملف robots.txt لدى Redfin. وتوفّر مغلّفات مفتوحة المصدر مثل reteps/redfin على PyPI وصولًا عبر Python، لكن استخدمها وأنت مدرك للمخاطر.
هل يمكنني تجريف Redfin دون Python؟
نعم. Thunderbit هو إضافة Chrome مدعومة بالذكاء الاصطناعي ترث جلسة متصفحك لمقاومة أنظمة مكافحة الروبوتات: ثبّتها، وانتقل إلى Redfin، وانقر على «AI Suggest Fields»، ثم صدّر إلى Excel أو Google Sheets أو Airtable أو Notion. وتوجد أيضًا أدوات تجريف أخرى بلا أكواد ومزوّدو مجموعات بيانات جاهزة في السوق إذا أردت استكشاف بدائل.
كم مرة يغيّر Redfin تخطيط موقعه؟
يُظهر سجل مشكلات GitHub لدى المجتمع أن محددات CSS تنكسر كل 6 إلى 12 شهرًا تقريبًا. وقد أطلق Redfin جيلين من DOM البطاقات: القديم (homecardV2Price وhomeAddressV2) والحالي (bp-Homecard__Price--value وbp-Homecard__Address). وأدوات التجريف الناضجة تجرّب الاثنين بالتتابع.
أما الأدوات القائمة على الذكاء الاصطناعي مثل Thunderbit فـتتكيّف تلقائيًا لأنها تكتشف الحقول عبر المحتوى لا عبر محددات CSS.
ما أفضل نوع بروكسي لتجريف Redfin؟
البروكسيات السكنية الأمريكية للتجريف واسع النطاق، إذ تشير قياسات المجتمع إلى معدل نجاح يقارب 80%. أما بروكسيات مراكز البيانات فتصطدم بخطأ Cloudflare 1020 على الفور تقريبًا؛ فنطاقات AWS وGCP وAzure وOVH مدرجة في القوائم السوداء. وتحقق البروكسيات الجوّالة أعلى معدل نجاح، لكن تكلفتها أعلى بـ 5 إلى 10 أضعاف.
وللتجريف الشخصي محدود النطاق (أقل من 100 صفحة)، قد تكفي الترويسات السليمة + انتحال curl_cffi + تأخيرات من 2 إلى 5 ثوانٍ دون أي بروكسيات على الإطلاق.
هل يمكنني تجريف بيانات العقارات المباعة أو خارج السوق من Redfin؟
نعم. تتوفر بيانات العقارات المباعة وتقدير Redfin للعقارات خارج السوق (بمتوسط خطأ 7.52%) في صفحات التفاصيل باستخدام المقاربات نفسها. لكن الحقول تختلف عن الإعلانات النشطة: فصفحات خارج السوق تعرض سعر البيع وتاريخه وتاريخ العقار ونقطة نهاية تقدير المالك، لكنها تفتقر إلى سعر الطلب الحالي وأيام العرض في السوق ومعلومات البيوت المفتوحة. ونقطة نهاية Stingray API الخاصة بتقديرات خارج السوق هي api/home/details/owner-estimate بدلًا من api/home/details/avm.
جرّب Thunderbit لاستخراج بيانات Redfin Get Started Free
اقرأ المزيد


