Redfin อัปเดต 70% ของประกาศใหม่จาก MLS ในสหรัฐฯ ภายในห้านาที หลังจากรายการเหล่านั้นถูกส่งเข้าระบบ ความสดระดับนี้นี่แหละที่คนทำ data pipeline ด้านอสังหาฯ ชอบกันสุด ๆ — และก็เป็นเหตุผลว่าทำไมสคริปต์ดึงข้อมูลจำนวนมากถึงพุ่งไปที่ Redfin แล้วโดนบล็อกภายในไม่กี่นาที
ผมทำงานกับเครื่องมือดึงข้อมูลที่ Thunderbit มาหลายปี และบอกได้เลยว่า: ช่องว่างระหว่าง "ดึงข้อมูลจาก Redfin" กับ "ดึงข้อมูลจาก Redfin โดยไม่โดนบล็อก" นี่แหละคือจุดที่บทความสอนส่วนใหญ่พัง พวกเขามักโชว์แค่โค้ด BeautifulSoup แล้วข้ามเรื่องที่ Cloudflare ตอบโต้คำขอของคุณแบบหนัก ๆ จากนั้นก็ปล่อยให้คุณนั่งมอง error 403 แบบงง ๆ ว่าพลาดตรงไหน คู่มือนี้ไม่ใช่แบบนั้น ผมจะพาคุณดู 3 แนวทางจริง — การ parse HTML, การใช้ API ที่ซ่อนอยู่ของ Redfin และแนวทางไม่ต้องเขียนโค้ดด้วย Thunderbit — พร้อมเจาะเรื่องระบบป้องกันบอทที่สำคัญจริง ๆ พออ่านจบ คุณจะรู้เลยว่าแต่ละวิธีเหมาะกับทักษะ ขนาดงาน และระดับความขี้เกียจในการดูแลระบบของคุณแบบไหน
ลองใช้ Thunderbit สำหรับดึงข้อมูล Redfin
Redfin คืออะไร และทำไมข้อมูลของมันถึงสำคัญ?
Redfin คือบริษัทนายหน้าอสังหาริมทรัพย์สายเทคโนโลยี มีเอเจนต์เงินเดือนประจำที่ดึงประกาศจากฟีด MLS โดยตรง ครอบคลุม เมืองใหญ่กว่า 100 แห่งในสหรัฐฯ และแคนาดา ครอบคลุม 42 รัฐ และมีผู้เข้าชมเกือบ 50 ล้านคนต่อเดือน ต่างจากพอร์ทัลที่เป็นแค่ตัวรวบรวมข้อมูล Redfin ใช้ข้อมูลที่เอเจนต์ยืนยันแล้ว และ Redfin Estimate AVM ของบริษัทครอบคลุม มากกว่า 95 ล้านทรัพย์สิน โดยมีค่าคลาดเคลื่อนมัธยฐานเพียง 1.96% สำหรับบ้านที่กำลังอยู่ในตลาด

การผสมกันของข้อมูลที่สดใกล้เคียง MLS คุณภาพที่ยืนยันโดยนายหน้า และ AVM ที่แม่นสูง ทำให้นักลงทุนอสังหาฯ เอเจนต์ สตาร์ทอัพ proptech และนักวิเคราะห์ข้อมูล ต่างต้องการเข้าถึงข้อมูล Redfin แบบโปรแกรมได้ Python เลยเป็นตัวเลือกที่เหมาะสุดสำหรับงานนี้ เพราะ ecosystem ด้าน scraping พร้อมมากอยู่แล้ว (requests, BeautifulSoup, Selenium, Playwright) ชุมชนผู้ใช้ก็ใหญ่ และต่อกับ pandas กับ Jupyter เพื่อวิเคราะห์ต่อได้ทันที
ทำไมต้องดึงข้อมูล Redfin ด้วย Python?
กรณีใช้งานมีหลากหลายพอ ๆ กับคนที่ต้องใช้ข้อมูล ต่อไปนี้คือวิธีที่กลุ่มผู้ใช้ต่าง ๆ เอาข้อมูลจาก Redfin ไปใช้กันเป็นหลัก:
| กลุ่มผู้ใช้ | เป้าหมายหลักในการดึงข้อมูล | ตัวอย่างการใช้งาน |
|---|---|---|
| เอเจนต์อสังหาฯ | หา lead, วิเคราะห์ตลาด | ประกาศใหม่และประกาศหมดอายุในพื้นที่ให้บริการ; ไดเรกทอรีเอเจนต์เพื่อเทียบคู่แข่ง |
| นักลงทุนอสังหาฯ | หาโอกาสลงทุน, วิเคราะห์ cap rate | คัดกรองผลตอบแทนค่าเช่า, หาอสังหาฯ ราคาต่ำกว่าตลาด, แจ้งเตือนประกาศใหม่รายวัน |
| สตาร์ทอัพ PropTech | สร้าง data pipeline สำหรับผลิตภัณฑ์ | ข้อมูลฝึก AVM, dashboard ตลาด, ระบบซื้อทรัพย์เพื่อขายต่อ |
| นักวิเคราะห์ข้อมูล | วิจัยตลาด, BI | แนวโน้มราคากลางระดับ ZIP code, time series ของวันค้างตลาด, อัตราส่วนราคาขายต่อราคาตั้ง |
| Wholesaler / Flipper | ติดตามอสังหาฯ มีปัญหา | ตรวจจับการลดราคา, foreclosures, เปรียบเทียบออฟมาร์เก็ต |
เทรนด์ภาพรวมก็ยืนยันเรื่องนี้เหมือนกัน: กว่า 72% ของบริษัทอสังหาฯ ใช้ predictive analytics เพื่อหาโอกาสและบริหารความเสี่ยง ตลาด PropTech คาดว่าจะโตถึง $47 พันล้านในปี 2025 ด้วยอัตราเติบโตเฉลี่ยต่อปี 16.4% ข้อมูลอสังหาฯ แบบมีโครงสร้างเลยไม่ใช่ของฟุ่มเฟือยอีกต่อไป — แต่มันคือของจำเป็นพื้นฐาน
ฟิลด์ข้อมูล Redfin ทั้งหมดที่คุณดึงได้ (อ้างอิงครบ)
ก่อนเขียนโค้ดแม้แต่บรรทัดเดียว คุณต้องรู้ก่อนว่ามีข้อมูลอะไรให้ใช้บ้าง ผมได้ไล่ดูหน้าผลการค้นหา หน้ารายละเอียดทรัพย์สิน และหน้าโปรไฟล์เอเจนต์ของ Redfin แล้ว เทียบกับ wrapper โค้ดเปิดอย่าง Stingray API เช่นโปรเจกต์ reteps/redfin และ RedfinPlus รวมแล้วนับได้ 117 ฟิลด์ที่แตกต่างกัน ครอบคลุมหลายประเภทของหน้า
ตารางนี้ควร bookmark ไว้เลย การรู้ schema ของข้อมูลตั้งแต่ต้นจะช่วยประหยัดเวลาหา selector แบบลองผิดลองถูกไปได้หลายชั่วโมง
ฟิลด์ในหน้าผลการค้นหา
นี่คือฟิลด์แบบเบาที่อยู่บนการ์ดประกาศ ซึ่งมักดึงได้โดยไม่ต้อง render JavaScript แบบเต็ม:
| ฟิลด์ | ชนิดข้อมูล | หมายเหตุ |
|---|---|---|
| Property ID | Number | รหัสภายในของ Redfin, แยกจาก /home/{id} ใน href |
| List price | Number | |
| ที่อยู่เต็ม | Text | |
| ห้องนอน / ห้องน้ำ / ตารางฟุต | Number | สามค่าที่เรียงกัน |
| ประเภททรัพย์สิน | Single Select | SFH, Condo, Townhouse, Multi |
| สถานะ | Text | Active, Pending, Contingent |
| จำนวนวันในตลาด | Number | |
| ตัวบ่งชี้ลดราคา | Number | ส่วนต่างจากราคาเริ่มต้น |
| รูปหลัก | Image URL | หนึ่งรูปต่อการ์ด |
| ป้าย Hot Home | Boolean | |
| วัน/เวลาเปิดบ้าน | Text | |
| ข้อมูลนายหน้า | Text |
ฟิลด์ในหน้ารายละเอียดทรัพย์สิน
หน้ารายละเอียดคือส่วนที่มีข้อมูลลึกจริง ๆ ฟิลด์หลายอย่างต้องใช้ JavaScript rendering หรือ Stingray API:
| ฟิลด์ | ชนิดข้อมูล | หมายเหตุ |
|---|---|---|
| Redfin Estimate (on-market) | Number | ผ่าน /stingray/api/home/details/avm |
| Redfin Estimate (off-market) | Number | ผ่าน /stingray/api/home/details/owner-estimate; ค่าคลาดเคลื่อนมัธยฐาน 7.52% |
| ปีที่สร้าง / ปรับปรุง | Number | |
| ขนาดที่ดิน | Number | |
| ค่าส่วนกลาง HOA | Number | รายเดือน ถ้ามี |
| ภาษีทรัพย์สิน (รายปี) | Number | |
| มูลค่าประเมินภาษี | Number | |
| ตารางประวัติการขาย | Table | ราคา, วันที่, ประเภทเหตุการณ์ |
| คำอธิบายทรัพย์สิน | Text | ย่อหน้าเชิงการตลาด |
| URL รูปภาพ (carousel) | Image URLs | มากกว่า 20 รูปต่อหนึ่งประกาศ |
| ชื่อเอเจนต์ เบอร์โทร อีเมล | Text / Phone / Email | เบอร์มักถูกปิดบางส่วน |
| คะแนนโรงเรียน (ประถม/มัธยมต้น/มัธยมปลาย) | Number | พร้อมชื่อเขตพื้นที่ |
| Walk / Transit / Bike Score | Number | |
| คะแนนความเสี่ยงด้านสภาพภูมิอากาศ | Number | น้ำท่วม ไฟป่า ความร้อน ลม |
| บ้านที่คล้ายกันที่ active / sold / ใกล้เคียง | URLs | ข้อมูลจาก carousel |
| ที่จอดรถ โรงรถ ระบบทำความร้อน ระบบทำความเย็น | Text | กลุ่มสิ่งอำนวยความสะดวก |
ฟิลด์ในหน้าโปรไฟล์เอเจนต์
| ฟิลด์ | ชนิดข้อมูล | หมายเหตุ |
|---|---|---|
| ชื่อเอเจนต์ รูป โปรไฟล์นายหน้า ประวัติย่อ | Text / Image | |
| โทรศัพท์ / ฟอร์มติดต่อ | Phone / Text | ต้องคลิกเพื่อแสดง |
| จำนวนประกาศที่ active | Number | |
| ยอดขาย 12 เดือนล่าสุด / มูลค่ารวม | Number | |
| อัตราส่วนราคาเฉลี่ยจากตั้งขายถึงปิดการขาย | Number | |
| ดาวรีวิว / จำนวนรีวิว | Number | |
| ปีประสบการณ์ / เลขใบอนุญาต | Text / Number |
เมื่อคุณใช้ฟีเจอร์ AI Suggest Fields ของ Thunderbit บนหน้า Redfin ระบบจะตรวจจับคอลัมน์ส่วนใหญ่ให้อัตโนมัติและกำหนดชนิดข้อมูลให้ถูกต้อง — ไม่ต้อง map CSS selector เองทีละอัน เดี๋ยวผมจะอธิบายต่อด้านล่าง
ถอดรหัสระบบป้องกันบอทของ Redfin (ไม่ใช่แค่ "ใช้ proxy")
ตรงนี้ผมอยากย้ำไว้ เพราะบทสอนส่วนใหญ่ชอบข้ามปัญหาการโดนบล็อก แล้วกระโดดไปที่ "ไปซื้อ proxy จากสปอนเซอร์เรา" ซึ่งไม่ช่วยอะไร ถ้าคุณไม่เข้าใจว่า Redfin ตรวจจับสคริปต์ดึงข้อมูลยังไง คุณก็จะเผาเครดิต proxy ไปเรื่อย ๆ แล้วสุดท้ายยังโดนบล็อกอยู่ดี ScrapeOps ให้คะแนนความยากของ anti-bot ของ Redfin ไว้ 7.5 จาก 10 และ Scraperly จัดอยู่ในระดับกลาง (3/5) — "ไม่ดุเท่า enterprise WAF ของ Zillow โดยอาศัย rate limiting แบบกำหนดเองและ JavaScript challenge"
Redfin ใช้สแต็กป้องกันหลายชั้น: Cloudflare ที่ขอบเครือข่าย (JS challenge, Turnstile, TLS/JA3 fingerprinting) ร่วมกับ ตัวจำกัดความถี่ระดับแอปของ Redfin เอง ไม่มีคำสั่ง Crawl-delay ใน robots.txt เพราะการบังคับใช้เกิดที่ชั้น WAF
ทำไม requests + BeautifulSoup แบบง่าย ๆ ถึงใช้ไม่ได้กับ Redfin
ถ้าคุณส่ง requests.get() ธรรมดาไปยังหน้าทรัพย์สินของ Redfin ด้วย header ค่าเริ่มต้น สิ่งที่มักเกิดขึ้นคือ:
- HTTP 403 — Cloudflare JS challenge ไม่ผ่าน คุณจะได้หน้า challenge แทนประกาศจริง
- หน้าท้าทายคั่นกลาง — body ของ HTML มี widget Turnstile ของ Cloudflare ไม่ใช่ข้อมูลทรัพย์สิน
- HTTP 200 แต่ HTML มาไม่ครบ — คุณจะได้โครงหน้าแบบ shell พร้อม JSON blob ฝังอยู่ใต้
root.__reactServerState.InitialContextแต่ไม่มีการ์ดค้นหาที่ render แล้ว ไม่มีประวัติราคา ไม่มีคะแนนโรงเรียน
Redfin ใช้ React SSR framework ของตัวเอง (ไม่ใช่ Next.js) และคีย์ hydration ก็เป็นแบบเฉพาะของ Redfin — root.__reactServerState.InitialContext โดยข้อมูลประกาศอยู่ใต้ ReactServerAgent.cache.dataCache ซึ่งไม่ใช่ __NEXT_DATA__ หรือ window.__INITIAL_STATE__
สาเหตุที่เจอ 403 แบบเงียบ ๆ บ่อยที่สุดคืออะไร? ขาด header Sec-Fetch-* Redfin/Cloudflare ตรวจสอบ Sec-Fetch-Site, Sec-Fetch-Mode, Sec-Fetch-Dest และ Sec-Fetch-User โดยตรง ถ้าไม่มี ระบบจะติดธงทันที
แผนรับมือ: หน่วงเวลา, Header, Proxy และ Session
นี่คือสรุปการป้องกันแต่ละชั้น พร้อมวิธีรับมือของแต่ละแบบ:
| กลไกป้องกันของ Redfin | ทำอะไร | สัญญาณที่ใช้ตรวจจับ | วิธีรับมือ |
|---|---|---|---|
| Cloudflare JS challenge | หน้าแทรกที่ออกคุกกี้ cf_clearance | 403 + body เป็น HTML ของ Cloudflare | ใช้ curl_cffi พร้อม impersonate="chrome120"; วอร์ม session ผ่านหน้าแรก; ใช้ US residential proxy |
| Cloudflare Turnstile | CAPTCHA แบบโต้ตอบใน session ที่เสี่ยงสูง | 403 + widget Turnstile | ใช้ headless browser แบบ stealth + residential proxy |
| Cloudflare Error 1020 (แบนตาม ASN) | บล็อก IP/ASN ที่ถูกระบุว่ามีความเสี่ยงใน WAF | body 403 ขึ้น "Error 1020 Access Denied" | เปลี่ยนไปใช้ residential/mobile proxy; อย่าใช้ datacenter ASN |
| TLS/JA3 fingerprinting | ตรวจจับ TLS stack ที่ไม่เหมือน browser | 403 เงียบ แม้ header จะถูกต้อง | ใช้ curl_cffi แบบ impersonation หรือ browser จริง |
| HTTP/2 fingerprinting | ตรวจ SETTINGS ของ HTTP/2 และลำดับ HPACK | บล็อกแบบเงียบ | curl_cffi พูด HTTP/2 เหมือน Chrome |
| ตรวจสอบ Header (UA, Sec-Fetch-*) | ชุด header ที่ต้องสอดคล้องกับ browser | 403 ตั้งแต่ request แรก | ใส่ Chrome header เต็มชุด รวม Sec-Fetch-Site/Mode/Dest/User, และ Referer ที่สมจริง |
| ความต่อเนื่องของ cookie/session | ติดตาม cf_clearance, RF_BROWSER_ID | เจอ challenge เมื่อเข้าลิงก์ลึกแบบสด ๆ | ใช้ Persistent Session; วอร์มหน้าแรกก่อน |
| Rate limit ระดับแอป | จำกัดจำนวน request ต่อ IP | 429 | หน่วง 2–5 วินาทีแบบสุ่ม; ใช้ exponential backoff |
| ชื่อเสียง IP จาก datacenter | บล็อก ASN ของศูนย์ข้อมูลที่รู้จักกันดี | 1020/403 ทันที | ใช้ residential หรือ mobile proxy เท่านั้น |
| ตรวจจับ concurrency | หลาย request พร้อมกันจาก IP เดียว | Turnstile โผล่ถี่ขึ้นแบบฉับพลัน | พร้อมกันต่อ IP ไม่เกิน 2 คำขอ |
ค่าขีดจำกัดที่ใช้งานได้จริงจากการทดสอบของชุมชน:
- จังหวะที่ปลอดภัย: 1 request ต่อ 2–3 วินาทีต่อ IP
- ถ้าระยะยาวเกิน 20–30 req/นาที จาก datacenter IP เดียว จะเริ่มเจอ challenge ภายในไม่กี่นาที
- soft rate-limit มักหายภายใน 5–15 นาทีเมื่อหยุดส่ง traffic
- การแบน datacenter IP (AWS, GCP, Azure, OVH) อาจอยู่ได้นานตั้งแต่หลายชั่วโมงถึงหลายวัน
requests มาตรฐานของ Python (urllib3 + OpenSSL) สร้าง JA3 fingerprint ที่ไม่ตรงกับ browser ใด ๆ — และจึงโดนบล็อกแบบเงียบ ๆ แม้ header จะครบ วิธีที่วงการนิยมคือ curl_cffi พร้อม impersonate="chrome120" ซึ่งพูด TLS + HTTP/2 ได้ใกล้เคียง Chrome มาก
3 วิธีดึงข้อมูล Redfin ด้วย Python (และควรเลือกแบบไหน)

ผมยังไม่เคยเจอบทความคู่แข่งที่เอาทั้ง 3 แนวทางมาเทียบกันแบบตรง ๆ เลย นี่คือตารางตัดสินใจ:
| เกณฑ์ | HTML Parsing (BS4 + Selenium) | Hidden API Stingray | Thunderbit (No-Code) |
|---|---|---|---|
| ความยากในการตั้งค่า | ปานกลาง (Python env + browser driver) | สูง (ต้อง reverse-engineer endpoint) | ต่ำ (ติดตั้ง Chrome extension) |
| ความเสี่ยงโดนบล็อก | สูง (request แบบ DOM มองเห็นง่ายที่สุด) | ปานกลาง (request สไตล์ API ดูธรรมชาติกว่า) | ต่ำสุด (ใช้ browser session จริงของคุณ) |
| คุณภาพโครงสร้างข้อมูล | ปานกลาง (HTML ไม่เป็นโครงสร้าง ต้อง parse เอง) | ดีเยี่ยม (JSON มีโครงสร้างอยู่แล้ว) | สูง (AI ตรวจจับฟิลด์และชนิดข้อมูลให้) |
| ภาระดูแลรักษา | สูง — layout เปลี่ยนที selector พัง | ปานกลาง — endpoint อาจเปลี่ยนโดยไม่แจ้ง | ต่ำสุด — AI ปรับตาม layout ได้ |
| ความสามารถในการสเกล | ต่ำ–ปานกลาง (หลักร้อยพร้อม proxies) | ปานกลาง–สูง (หลักพัน, request ดูสะอาดกว่า) | ปานกลาง (50 หน้า/รอบผ่าน cloud scraping) |
| เหมาะที่สุดสำหรับ | นักพัฒนาที่ต้องการคุมทุกอย่าง | นักพัฒนาที่ต้องการ JSON สะอาด ๆ | คนไม่เขียนโค้ด, งานเร็ว, งานต่อเนื่องที่ไม่มีทีม dev รองรับ |
เรื่องการดูแลรักษาสำคัญมาก Redfin เคยเปลี่ยน DOM ของการ์ดมาสองยุค — แบบเก่า (homecardV2Price) และแบบปัจจุบัน (span.bp-Homecard__Price--value) ประวัติ issue ใน GitHub ของชุมชนแสดงให้เห็นว่าการพังของ CSS selector เกิดขึ้นราวทุก 6–12 เดือน พอเกิดขึ้น scraper ที่พึ่ง BeautifulSoup จะพังข้ามคืน แต่ระบบตรวจจับฟิลด์ด้วย AI จะปรับตัวได้
ก่อนเริ่ม
- ระดับความยาก: ปานกลาง (แนวทาง 1 และ 2), เริ่มต้น (แนวทาง 3)
- เวลาที่ต้องใช้: ประมาณ 30 นาทีสำหรับแนวทาง 1 หรือ 2; ประมาณ 5 นาทีสำหรับแนวทาง 3
- สิ่งที่ต้องมี:
- Python 3.8+ พร้อม pip (แนวทาง 1 และ 2)
- เบราว์เซอร์ Chrome (ทุกแนวทาง)
- Thunderbit Chrome Extension (แนวทาง 3)
- US residential proxies สำหรับงานสเกลใหญ่ (แนวทาง 1 และ 2)
ดึงข้อมูล Redfin ด้วย AI Get Started Free
แนวทางที่ 1: ดึงข้อมูล Redfin ด้วย Python แบบ parse HTML (BeautifulSoup + Selenium)
นี่คือเส้นทางแบบ "คุมได้ทั้งหมด" คุณเขียน selector เอง ดูแล browser เอง และจัดการ error เอง
เป็นวิธีที่ให้ความรู้ที่สุด และก็เปราะบางที่สุดด้วย
ขั้นตอนที่ 1: ตั้งค่า Python environment
สร้าง virtual environment และติดตั้งไลบรารีที่จำเป็น:
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 request ของคุณเลียนแบบ TLS fingerprint ของ Chrome จริง ๆ แทน fingerprint มาตรฐานของ requests ใน Python ที่ Cloudflare มองเห็นแล้วบล็อกทันที
ขั้นตอนที่ 2: ตั้งค่า header ของเบราว์เซอร์และ session
ตรงนี้คือจุดที่มือใหม่ส่วนใหญ่พลาด คุณต้องใส่ Chrome header ให้ครบ รวมถึง Sec-Fetch-* headers ที่ 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)
# วอร์ม session — เก็บคุกกี้ cf_clearance และ RF_BROWSER_ID
session.get("https://www.redfin.com/")
ขั้นตอนวอร์ม session สำคัญมาก — ถ้าเข้า deep URL ของทรัพย์สินแบบสด ๆ (ไม่มีคุกกี้ก่อนหน้าและไม่มี Referer) จะโดน Cloudflare มองว่าเสี่ยงสูงขึ้น
เริ่มจากหน้าแรกเสมอ
ขั้นตอนที่ 3: ดึงผลการค้นหาของ Redfin
เมื่อ session พร้อมแล้ว คุณสามารถเรียกหน้าค้นหาของเมืองและ parse การ์ดประกาศได้ selector รุ่นปัจจุบัน (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"โดนบล็อกที่หน้า {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"ดึงข้อมูลได้ {len(listings)} รายการ")
คุณควรจะเห็นลิสต์ dictionary ที่เพิ่มขึ้นเรื่อย ๆ โดยแต่ละรายการมีราคาบ้านใน San Francisco ที่อยู่ จำนวนห้องนอน/ห้องน้ำ/ตารางฟุต และลิงก์รายละเอียด ถ้าได้ cards เป็น 0 ให้เช็ก HTTP status code — ถ้าเป็น 403 แปลว่า Cloudflare จับได้ และคุณอาจต้องใช้ residential proxy
ขั้นตอนที่ 4: ดึงข้อมูลจากหน้ารายละเอียดแต่ละทรัพย์สิน
หน้าผลการค้นหาให้ข้อมูลพื้นฐาน ส่วนหน้ารายละเอียดให้ Redfin Estimate ปีที่สร้าง HOA ประวัติการขาย ข้อมูลเอเจนต์ และรูปภาพ หน้าเหล่านี้ต้อง render 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)) # รอให้ JS render
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()
หลังทำขั้นตอนนี้ Listing 10 รายการแรกควรมีค่า Redfin Estimate และข้อมูลปีที่สร้างแล้ว XPath selectors มักทนต่อฟิลด์ amenity ที่ซ้อนกันได้ดีกว่า CSS แต่ก็ยังเปราะบาง — ถ้า DOM ถูกปรับใหม่เมื่อไร selector ก็พังอยู่ดี
ขั้นตอนที่ 5: รับมือการบล็อกและ error
เพิ่ม logic ลองใหม่พร้อม exponential backoff:
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"โดนบล็อก ({resp.status_code}) จะลองใหม่ใน {wait:.1f} วินาที...")
time.sleep(wait)
else:
print(f"สถานะไม่คาดคิด: {resp.status_code}")
break
return None
สัญญาณว่าโดนบล็อก ได้แก่ HTTP 403 พร้อม HTML ของ Cloudflare ใน body, HTTP 429 (rate limit ตรง ๆ), body ว่างเปล่า หรือมีคำว่า "Error 1020 Access Denied" อยู่ในเนื้อหา ถ้าเจอแบบนี้ซ้ำ ๆ ก็ถึงเวลาต้องเพิ่ม residential proxy หรือเปลี่ยนไปใช้แนวทาง API
แนวทางที่ 2: ดึงข้อมูล Redfin ด้วย Python ผ่าน Hidden Stingray API
นี่คือวิธีที่ผมชอบที่สุด ฝั่ง frontend ของ Redfin คุยกับ internal JSON API ที่ /stingray/api/home/details/* และ response ที่ได้กลับมาเป็น JSON ที่สะอาดและมีชนิดข้อมูลชัดเจน — ไม่ต้อง parse HTML เลย
วิธีหา endpoint ของ Hidden API ของ Redfin
เปิด Chrome DevTools → แท็บ Network → กรองด้วย Fetch/XHR → เข้าไปที่หน้าทรัพย์สินของ Redfin สักหน้า คุณจะเห็น request ไปยัง endpoint เช่น:
api/home/details/initialInfo— แกะ URL → propertyId, listingIdapi/home/details/aboveTheFold— ราคา, ห้องนอน, ห้องน้ำ, ตารางฟุต, รูปภาพ, สถานะ, เอเจนต์, MLS#api/home/details/belowTheFold— สิ่งอำนวยความสะดวก, HOA, ภาษี, ที่จอดรถ, ปีที่สร้าง, ขนาดที่ดิน, ประวัติapi/home/details/avm— Redfin Estimate สำหรับทรัพย์ในตลาดapi/home/details/owner-estimate— Redfin Estimate สำหรับทรัพย์นอกตลาดapi/home/details/descriptiveParagraph— คำอธิบายเชิงการตลาด
สำหรับหน้ารายการเช่า rentalId (UUID 36 ตัวอักษร) จะถูกดึงจาก URL ของแท็ก <meta property="og:image">
ดึงข้อมูลทรัพย์สินผ่าน Stingray API
มีข้อควรรู้สำคัญ: response แบบ JSON ของ Stingray จะมี prefix เป็นสตริง literal {}&& เพื่อป้องกัน CSRF คุณต้องลบส่วนนี้ก่อน parse:
import json
from curl_cffi import requests as curl_requests
session = curl_requests.Session(impersonate="chrome120")
session.headers.update(HEADERS)
# วอร์ม session
session.get("https://www.redfin.com/")
# ดึงหน้าทรัพย์สินเพื่อรับคุกกี้และ property ID
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})
# ตัด prefix anti-CSRF ออก
payload = json.loads(api_resp.text.replace("{}&&", "", 1))
# ดึงข้อมูลแบบมีโครงสร้าง
listing_data = payload.get("payload", {})
print(json.dumps(listing_data, indent=2))
response จะมีฟิลด์ที่เป็นชนิดข้อมูลชัดเจน: ราคาเป็น integer, beds/baths เป็นตัวเลข, URL รูปภาพเป็น array, ข้อมูลเอเจนต์เป็น object ซ้อนกัน ไม่มีการ parse HTML ไม่มี CSS selectors และไม่ต้องเดา
ข้อดีและข้อจำกัดของแนวทาง Hidden API
ข้อดี:
- JSON มีโครงสร้างพร้อมใช้ — สะอาดกว่า HTML parsing มาก
- เร็วกว่าในแต่ละ request (payload เล็กกว่า ไม่ต้อง render)
- ความเสี่ยงโดนบล็อกต่ำกว่า (request แบบ API ที่มี header ถูกต้องดูธรรมชาติกว่า)
ข้อจำกัด:
- Endpoint อาจเปลี่ยนได้โดยไม่แจ้ง — ไม่มีเอกสารทางการ
robots.txtห้าม/stingray/สำหรับ user-agent แบบ wildcard อย่างชัดเจน- ต้อง reverse-engineer เพื่อหา endpoint ใหม่ ๆ
- ยังต้องวอร์ม session และใส่ header ให้ถูกต้องเพื่อเลี่ยง Cloudflare
ทางเลือกแบบไม่ต้องเขียนโค้ด: ดึงข้อมูล Redfin ด้วย Thunderbit
ถ้าคุณต้องการข้อมูล Redfin แต่ไม่อยากดูแล Python scripts — หรือแค่อยากได้ผลลัพธ์ภายในห้านาที — เริ่มจากตรงนี้ก่อน เราสร้าง Thunderbit ขึ้นมาเพื่อสิ่งนี้โดยตรง: ดึงข้อมูลแบบมีโครงสร้างจากเว็บไซต์ใดก็ได้ โดยไม่ต้องเขียนโค้ด
ขั้นตอนที่ 1: ติดตั้ง Thunderbit แล้วเข้า Redfin
ติดตั้ง Thunderbit Chrome Extension จาก Chrome Web Store เปิด Redfin แล้วไปที่หน้าผลการค้นหา เช่น บ้านขายใน San Francisco
ขั้นตอนที่ 2: คลิก "AI Suggest Fields"
คลิกไอคอน Thunderbit ที่แถบเครื่องมือของเบราว์เซอร์ จากนั้นคลิก "AI Suggest Fields" AI จะอ่านหน้า Redfin แล้วเสนอคอลัมน์ให้อัตโนมัติ เช่น "Address," "Price," "Beds," "Baths," "SqFt," "Property Type," และ "Listing Photo" — พร้อมกำหนดชนิดข้อมูลให้ถูกต้องโดยอัตโนมัติ
คุณสามารถลบคอลัมน์ที่ไม่ต้องการ หรือเพิ่มคอลัมน์เองด้วยการคลิก "+ Add Column" แล้วพิมพ์สิ่งที่ต้องการเป็นภาษาธรรมดา เช่น "ชื่อเอเจนต์" หรือ "จำนวนวันในตลาด"
คุณจะเห็นตัวอย่างตารางที่ตั้งค่าไว้เรียบร้อย พร้อมเริ่มดึงข้อมูลได้ทันที
ขั้นตอนที่ 3: กด "Scrape" แล้วดูข้อมูลไหลเข้าตาราง
คลิกปุ่ม "Scrape" Thunderbit จะประมวลผลประกาศที่มองเห็นอยู่และเติมข้อมูลลงตารางให้ ถ้าเป็นผลลัพธ์หลายหน้า ระบบจะจัดการ pagination ให้เอง — ไม่ต้องเขียน loop
จากที่ผมทดสอบ ตาราง 50 แถวใช้เวลาประมาณ 45 วินาที ข้อมูลมีโครงสร้าง และ export ต่อได้ทันที
Thunderbit รับมือระบบป้องกันบอทของ Redfin ยังไง
เพราะ Thunderbit ทำงานใน browser ของคุณเอง จึงใช้คุกกี้ Session และ browser fingerprint ของ Redfin ที่คุณมีอยู่แล้ว Cloudflare เลยเห็นมันเป็นผู้ใช้จริงที่กำลังเข้าเว็บ Redfin — เพราะในทางเทคนิคมันก็คือการใช้งานจริง ไม่มี headless browser ไม่มี IP จาก datacenter ไม่มี TLS fingerprint แปลก ๆ สำหรับหน้าสาธารณะ Thunderbit mode แบบ cloud scraping สามารถประมวลผลได้ครั้งละ 50 หน้า
นั่นต่างจากการยิง requests จาก Python script บนเซิร์ฟเวอร์แบบคนละโลก
Session ของเบราว์เซอร์คุณได้รับความเชื่อถืออยู่แล้ว
ดึงข้อมูลหน้าย่อยของ Redfin ด้วย Thunderbit
หลังดึงผลการค้นหาแล้ว ให้คลิก "Scrape Subpages" เพื่อให้ AI เข้าไปยังลิงก์รายละเอียดของแต่ละทรัพย์และเติมข้อมูลเพิ่มลงในตาราง เช่น Redfin Estimate, ปีที่สร้าง, ค่า HOA, ข้อมูลเอเจนต์, รูปภาพทรัพย์สิน และประวัติการขาย
นี่เทียบเท่ากับ Selenium loop 40 บรรทัดในแนวทางที่ 1 — แต่ทำได้ด้วยการคลิกครั้งเดียวและไม่ต้องคอยดูแลโค้ดต่อ
เมื่อ Redfin เปลี่ยน DOM จาก homecardV2Price เป็น span.bp-Homecard__Price--value AI ก็ปรับตัวได้ แต่ selector ใน Python ของคุณไม่สามารถทำแบบนั้น
ดึงหน้าย่อยของ Redfin ด้วย AI Get Started Free
มากกว่า CSV: ส่งออกข้อมูล Redfin ไป Google Sheets, Airtable และ Notion
บทความสอนส่วนใหญ่หยุดแค่ df.to_csv() ซึ่งพอสำหรับการวิเคราะห์ครั้งเดียว แต่ถ้าคุณอยู่ในทีมอสังหาฯ คุณต้องการข้อมูลที่ใช้งานร่วมกันได้และอัปเดตต่อเนื่อง ไม่ใช่ไฟล์นิ่ง ๆ ที่เก็บฝุ่นอยู่บนเดสก์ท็อปของใครสักคน
การส่งออกด้วย Python (gspread + Airtable API)
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)
# แสดงรูปทรัพย์สินแบบ inline ด้วยสูตร 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 ล้านเซลล์ต่อ spreadsheet และ API รองรับ 300 read + 300 write requests ต่อนาทีต่อโปรเจกต์ ถ้าเกินหลักไม่กี่สิบแถว ควรใช้ ws.batch_update() แทนการ loop อัปเดตทีละเซลล์
Airtable ผ่าน pyairtable:
การเปลี่ยนแปลงสำคัญปี 2024: Airtable ยกเลิก legacy API keys ตั้งแต่ 1 กุมภาพันธ์ 2024 ตอนนี้คุณต้องใช้ Personal Access Tokens (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 requests/วินาทีต่อหนึ่ง base และจะล็อก 30 วินาทีหากละเมิด ฟิลด์ attachment รองรับ payload แบบ [{"url": ...}] — เซิร์ฟเวอร์ของ Airtable จะไปดึง URL นั้นมา re-host บน CDN และสร้าง thumbnail ให้อัตโนมัติ
การส่งออกด้วย Thunderbit (คลิกครั้งเดียวไป Sheets, Airtable, Notion)
Thunderbit มีการ export แบบคลิกครั้งเดียวไปยัง Google Sheets, Airtable และ Notion แบบ native — และส่วนที่ผมชอบจริง ๆ คือรูปภาพทรัพย์สินจะถูกอัปโหลดและแสดงเป็น inline images ใน Notion และ Airtable ไม่ต้องใช้สูตร =IMAGE() แบบอ้อม ๆ และไม่ต้องลุ้นลิงก์ CDN เสีย คุณคลิก "Export to Airtable" แล้วทีมของคุณจะได้ฐานข้อมูลทรัพย์สินแบบเห็นภาพ พร้อม thumbnail ให้เปิดดูบนมือถือได้
สำหรับทีมอสังหาฯ ที่ต้องคัดกรองประกาศแบบเห็นภาพ นี่คือความต่างระหว่างเครื่องมือที่ใช้งานได้จริงกับกอง CSV ที่อ่านยาก
การ scraping Redfin ถูกกฎหมายไหม? robots.txt, ToS และแนวคดีว่าอย่างไร
ผมไม่ใช่ทนาย และนี่ไม่ใช่คำแนะนำทางกฎหมาย แต่จากประสบการณ์ในสาย data extraction มาหลายปี ผมบอกได้ว่า "มันถูกกฎหมายไหม" คือคำถามที่ทุกคนถาม และบทความสอนส่วนใหญ่ชอบเลี่ยง
robots.txt ของ Redfin
robots.txt ของ Redfin ค่อนข้างละเอียด จุดสำคัญคือ:
- บอทที่ถูกบล็อกแบบชัดเจน:
peer39_crawler/1.0,AmazonAdBot,FireCrawlAgent— Redfin ระบุชื่อบริการ scraping สาย LLM ที่คนใช้กันเยอะไว้ตรง ๆ - จุดที่
User-agent: *ห้ามเข้าถึง:/stingray/(namespace ของ internal API ทั้งหมด),/myredfin/,/api/v1/rentals/,/api/v1/properties/,/owner-estimate/ - ไม่มีคำสั่ง
Crawl-delay:สำหรับ user agent ใด ๆ - ประกาศ sitemap กว่า 50 รายการ — sitemap คือวิธีไล่ URL ที่สะอาดและกระทบ WAF น้อยที่สุด
เงื่อนไขการใช้งานของ Redfin
ข้อ 2.3.5 ระบุว่า: "You may not automatedly crawl or query the Services for any purpose or by any means... unless you have received prior express written permission."
นี่เป็นข้อตกลงแบบ browsewrap — คือการยอมรับจากการใช้งานต่อเนื่อง ไม่ใช่ clickwrap ศาลสหรัฐฯ มักลังเลที่จะบังคับใช้ browsewrap กับผู้ใช้ที่ไม่ได้รับแจ้งจริง ๆ (ดู Nguyen v. Barnes & Noble, 9th Cir. 2014)
แนวคำพิพากษาที่เกี่ยวข้องแบบย่อ
- Van Buren v. United States (ศาลสูงสุดสหรัฐฯ, 2021): บทบัญญัติ "exceeds authorized access" ใน CFAA ใช้การทดสอบแบบ "gate เปิดหรือปิด" การเปิดประตูที่มีอยู่แล้วเพื่อจุดประสงค์ที่ไม่พึงประสงค์ ไม่ใช่การแฮ็กตามกฎหมายอาญาของรัฐบาลกลาง
- hiQ Labs v. LinkedIn (9th Cir., 2022): การ scraping ข้อมูลสาธารณะไม่ถือเป็นการละเมิด CFAA แต่ hiQ สุดท้ายยอมจ่าย 500,000 ดอลลาร์ในการยอมความในประเด็น breach-of-contract เพราะ hiQ เคยสมัครบัญชี LinkedIn และกด "I agree"
- Meta Platforms v. Bright Data (N.D. Cal., ม.ค. 2024): ศาลมีคำพิพากษาแบบ summary judgment ให้ Bright Data — การ scraping ข้อมูลสาธารณะในสถานะที่ไม่ได้ล็อกอินไม่ทำให้ Bright Data เป็น "user" ที่ต้องผูกพันตาม ToS ของ Meta
- X Corp. v. Bright Data (N.D. Cal., พ.ค. 2024): ผู้พิพากษา Alsup ยกฟ้องข้อเรียกร้องของ X โดยเห็นว่าคำร้องตามกฎหมายรัฐที่พยายามควบคุมการคัดลอกเนื้อหาสาธารณะถูกกฎหมายลิขสิทธิ์รัฐบาลกลางครอบทับ
คำแนะนำเชิงปฏิบัติ
- ดึงเฉพาะข้อมูลที่เข้าถึงได้แบบสาธารณะ — อย่าสมัครบัญชีแล้วค่อย scrape (เพราะจะสร้างความเสี่ยงเรื่อง clickwrap contract)
- เคารพ rate limit — ปริมาณที่แรงเกินไปอาจถูกยกไปเป็นข้อเรียกร้องเรื่อง trespass-to-chattels ได้
- อย่านำข้อมูลดิบหรือรูปภาพไปเผยแพร่ซ้ำในวงกว้าง — คดี CoStar v. Zillow (ยื่นฟ้องกรกฎาคม 2025, ค่าเสียหายอาจเกิน 1 พันล้านดอลลาร์) เป็นเครื่องเตือนว่าเรื่องลิขสิทธิ์ภาพไม่ใช่เรื่องเล็ก
- แนวทางของ Thunderbit ที่ทำงานผ่าน browser ของคุณเอง — ใช้ session ที่คุณล็อกอินอยู่แล้ว — ใกล้เคียงกับ "การเปิดเว็บด้วยมือในความเร็วเครื่องจักร" มากกว่า bot บน datacenter แบบ headless ซึ่งเป็นท่าทีที่ป้องกันตัวได้ดีกว่าถ้ายังไม่ถึงขั้นใช้ API ที่มีใบอนุญาต
เคล็ดลับและข้อผิดพลาดที่พบบ่อย
นี่คือบทเรียนที่ได้มาจากการสร้างเครื่องมือดึงข้อมูลและเห็นผู้ใช้หลายพันคน scrape เว็บไซต์อสังหาฯ:
- วอร์ม session ทุกครั้ง ก่อนเข้า deep URL ให้เรียก
redfin.com/ก่อนเสมอ การเข้า deep URL แบบสด ๆ คือสาเหตุอันดับ 1 ที่ทำให้โดน Cloudflare challenge - สลับ User-Agent ให้สมจริง อย่าใช้ค่าเดียวตลอด ควรสลับระหว่าง UA ของ Chrome/Firefox รุ่นปัจจุบัน 5–10 แบบ แต่ก็อย่าสลับถี่เกินไป (UA ใหม่ทุก request ดูน่าสงสัย)
- ลบข้อมูลซ้ำตาม Property ID pagination ของ Redfin บางครั้งซ้อนกัน แยก
/home/{id}จาก URL ของแต่ละประกาศแล้วค่อย deduplicate ก่อน enrichment - ถ้าเลี่ยงได้ อย่า scrape ตอนชั่วโมงพีก จากประสบการณ์ของผม ช่วงดึกหรือเช้าตรู่ตามเวลา US จะเจอการตรวจ WAF น้อยกว่า
- ถ้าได้ 429 ให้ถอยแบบทวีคูณ อย่าลองใหม่ทันที — นั่นคือทางลัดจาก soft rate limit ไปสู่การแบน IP แบบถาวร
- ถ้างานใหญ่ (1,000+ หน้า) ให้กันงบสำหรับ residential proxy IP จาก datacenter (AWS, GCP, Azure, OVH) จะถูกบล็อกโดยระบบ reputation ของ ASN ของ Cloudflare คุณจะเจอ Error 1020 เกือบทันที
เลือกวิธีที่เหมาะกับการดึงข้อมูล Redfin
แล้วควรเลือกแนวทางไหนดี? ขึ้นอยู่กับว่าคุณเป็นใคร และต้องการอะไร
HTML Parsing (BeautifulSoup + Selenium): เหมาะที่สุดสำหรับนักพัฒนาที่อยากคุมทุกอย่างเอง รับได้กับการดูแล CSS selector และไม่ติดใจหากต้องสร้างใหม่เมื่อ Redfin เปลี่ยน DOM คาดว่าจะต้องกลับมาแก้โค้ดทุก 6–12 เดือน
Hidden Stingray API: เหมาะที่สุดสำหรับนักพัฒนาที่ต้องการ JSON ที่สะอาดและมีโครงสร้าง พร้อมรับมือกับการ reverse-engineer endpoint ที่ไม่ได้เอกสารไว้ ภาระดูแลรักษาต่ำกว่า HTML parsing แต่ endpoint อาจเปลี่ยนโดยไม่แจ้ง และอย่าลืมว่า /stingray/ ถูกห้ามไว้ใน robots.txt อย่างชัดเจน
Thunderbit (No-Code): เหมาะที่สุดสำหรับคนไม่เขียนโค้ด งานเร็ว และทีมที่ต้องใช้ข้อมูล Redfin ต่อเนื่องโดยไม่มีทรัพยากร developer AI ปรับตาม layout ได้ การ scrape หน้าย่อยช่วยเติมข้อมูลด้วยการคลิกเดียว และมีการ export ไป Google Sheets, Airtable หรือ Notion ในตัว ถ้าคุณเป็นทีมอสังหาฯ ที่อยากได้ฐานข้อมูลทรัพย์สินที่ใช้งานต่อได้จริง — ไม่ใช่แค่กอง CSV ครั้งเดียวจบ — นี่คือทางที่ราบที่สุด
ไม่ว่าคุณจะเลือกทางไหน: ทำความเข้าใจระบบป้องกันบอทของ Redfin ก่อนเริ่ม รู้ว่าคุณต้องการฟิลด์อะไร เลือกรูปแบบ export ให้เข้ากับ workflow ของทีม และอยู่บนฝั่งที่ถูกต้องของ แนวทางทางกฎหมาย
พร้อมลองทาง no-code แล้วหรือยัง? แผนฟรีของ Thunderbit ให้คุณทดลองดึงข้อมูลจาก Redfin และเห็นผลได้ภายในไม่กี่นาที ส่วนแนวทาง Python โค้ดตัวอย่างด้านบนคือจุดเริ่มต้นที่ใช้งานได้จริง — แค่เติม proxy และความอดทนเข้าไป
ลองใช้ Thunderbit สำหรับข้อมูล Redfin ระยะยาว
คำถามที่พบบ่อย
Redfin มี public API ไหม?
ไม่มี Redfin ไม่มี public API อย่างเป็นทางการ Hidden Stingray API (/stingray/api/home/details/*) ให้ JSON ที่มีโครงสร้างและถูกใช้โดย frontend ของ Redfin เอง แต่ไม่เป็นทางการ ไม่มีเอกสาร และอาจเปลี่ยนได้โดยไม่แจ้ง พร้อมทั้งถูกห้ามไว้ใน robots.txt ของ Redfin อย่างชัดเจน wrapper แบบโอเพนซอร์สอย่าง reteps/redfin บน PyPI ช่วยให้เข้าถึงด้วย Python ได้ แต่ควรใช้อย่างเข้าใจความเสี่ยง
ดึงข้อมูล Redfin โดยไม่ใช้ Python ได้ไหม?
ได้ Thunderbit คือ Chrome extension ที่ใช้ AI และอาศัย session ของเบราว์เซอร์คุณเพื่อความทนทานต่อระบบป้องกันบอท — แค่ติดตั้ง เข้า Redfin คลิก "AI Suggest Fields" แล้ว export ไป Excel, Google Sheets, Airtable หรือ Notion นอกจากนี้ยังมีเครื่องมือ scraping แบบ no-code และผู้ให้บริการ dataset สำเร็จรูปในตลาดอีกหลายรายถ้าอยากสำรวจตัวเลือกอื่น
Redfin เปลี่ยน layout เว็บไซต์บ่อยแค่ไหน?
จากประวัติ issue บน GitHub ของชุมชน พบว่า selector ที่พังเพราะเปลี่ยน CSS เกิดขึ้นราวทุก 6–12 เดือน Redfin เคยใช้ DOM ของการ์ดสองยุค — แบบเก่า (homecardV2Price, homeAddressV2) และแบบปัจจุบัน (bp-Homecard__Price--value, bp-Homecard__Address) scraper ที่ดีมักลองทั้งสองชุดตามลำดับ
เครื่องมือที่ใช้ AI อย่าง Thunderbit ปรับตัวอัตโนมัติ เพราะตรวจจับฟิลด์จากเนื้อหา ไม่ได้ยึดติดกับ CSS selector
proxy แบบไหนเหมาะที่สุดสำหรับการ scrape Redfin?
US residential proxy เหมาะที่สุดสำหรับงานสเกลใหญ่ — benchmark ของชุมชนให้ success rate ราว 80% ส่วน datacenter proxy มักเจอ Cloudflare Error 1020 แทบจะทันที ช่วง IP ของ AWS, GCP, Azure และ OVH มักถูก blacklist ไปแล้ว Mobile proxy มีอัตราความสำเร็จสูงสุด แต่ราคาแพงกว่าประมาณ 5–10 เท่า
สำหรับงานส่วนตัวขนาดเล็ก (<100 หน้า) การใส่ header ให้ถูกต้อง + ใช้ curl_cffi แบบ impersonation + หน่วงเวลา 2–5 วินาที อาจใช้ได้โดยไม่ต้องมี proxy เลย
ดึงข้อมูลทรัพย์สินที่ขายแล้วหรืออยู่นอกตลาดจาก Redfin ได้ไหม?
ได้ ข้อมูลทรัพย์สินที่ขายแล้วและ Redfin Estimate สำหรับทรัพย์นอกตลาด (ค่าคลาดเคลื่อนมัธยฐาน 7.52%) มีอยู่ในหน้ารายละเอียดและดึงได้ด้วยแนวทางเดียวกัน ฟิลด์จะแตกต่างจากประกาศที่ยัง active: หน้านอกตลาดจะแสดงราคาขาย วันที่ขาย ประวัติทรัพย์สิน และ endpoint สำหรับ owner-estimate แต่จะไม่มี list price ปัจจุบัน จำนวนวันในตลาด และข้อมูล open house ส่วน endpoint ของ Stingray สำหรับการประเมินนอกตลาดคือ api/home/details/owner-estimate แทน api/home/details/avm
ลองใช้ Thunderbit สำหรับดึงข้อมูล Redfin Get Started Free
อ่านเพิ่มเติม


