[object Object]

← back to Rentv Licensed Targets

scraper: CA DRE subdivider -> CA developers

9beee1a9f7d2985a06ca69a8105a8ce6097e532f · 2026-07-31 06:51:50 -0700 · Steve

Files touched

Diff

commit 9beee1a9f7d2985a06ca69a8105a8ce6097e532f
Author: Steve <steve@designerwallcoverings.com>
Date:   Fri Jul 31 06:51:50 2026 -0700

    scraper: CA DRE subdivider -> CA developers
---
 scrapers/ca_dre_subdivider.py | 65 +++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 65 insertions(+)

diff --git a/scrapers/ca_dre_subdivider.py b/scrapers/ca_dre_subdivider.py
new file mode 100644
index 0000000..f39c052
--- /dev/null
+++ b/scrapers/ca_dre_subdivider.py
@@ -0,0 +1,65 @@
+#!/usr/bin/env python3
+# CA DRE New Subdivision Filing List (.xls) → CSV for realestate.rentv_licensed_targets (role=Developer).
+# Subdivider = the developer. Feed-first, no auth. Filters SoCal counties, dedups by subdivider.
+import urllib.request, csv, sys, io, hashlib
+import xlrd
+
+SOCAL = {'LOS ANGELES':'Greater LA','ORANGE':'Orange County','RIVERSIDE':'Inland Empire',
+         'SAN BERNARDINO':'Inland Empire','SAN DIEGO':'San Diego','VENTURA':'Ventura'}
+UA = {'User-Agent':'Mozilla/5.0 Chrome/126'}
+
+def months():
+    for yy in (2024, 2025, 2026):
+        for mm in range(1, 13):
+            if yy == 2026 and mm > 7: break
+            yield yy, mm
+
+def col_idx(header):
+    h = {str(c).strip().lower(): i for i, c in enumerate(header)}
+    def find(*names):
+        for n in names:
+            if n in h: return h[n]
+        return None
+    return {
+        'file': find('file number'), 'county': find('county name'),
+        'subtype': find('subdivision subtype code'), 'subdivider': find('subdivider'),
+        'phone': find('phone number'), 'addr1': find('address line 1'), 'addr2': find('address line 2'),
+        'city': find('city name'), 'state': find('usps state code'), 'zip': find('zip code'),
+        'tract': find('tract number'), 'subname': find('subdivision name'), 'filed': find('filed'),
+    }
+
+seen = set()
+rows = []
+for yy, mm in months():
+    url = f"https://www.dre.ca.gov/files/excel/{yy}/subdivider_list_{mm:02d}_{str(yy)[2:]}.xls"
+    try:
+        data = urllib.request.urlopen(urllib.request.Request(url, headers=UA), timeout=30).read()
+        if len(data) < 5000: continue
+        wb = xlrd.open_workbook(file_contents=data)
+    except Exception:
+        continue
+    sh = wb.sheet_by_index(0)
+    ci = col_idx(sh.row_values(0))
+    if ci['subdivider'] is None or ci['county'] is None: continue
+    for r in range(1, sh.nrows):
+        row = sh.row_values(r)
+        county = str(row[ci['county']]).strip().upper()
+        if county not in SOCAL: continue
+        sub = str(row[ci['subdivider']]).strip()
+        if not sub: continue
+        key = sub.lower()
+        if key in seen: continue
+        seen.add(key)
+        g = lambda k: (str(row[ci[k]]).strip() if ci[k] is not None else '')
+        rows.append([
+            'ca_dre_subdivision', 'Developer', sub, '',
+            g('file') or ('cadre-'+hashlib.md5(key.encode()).hexdigest()[:10]),
+            g('subtype') or 'Subdivision', 'Filed',
+            g('addr1'), g('city'), county.title(), g('state') or 'CA', g('zip'), g('phone'), '',
+            SOCAL[county], 't', 't', url,
+            f'{{"tract":"{g("tract")}","subdivision":"{g("subname")}"}}'.replace('\\','')
+        ])
+
+w = csv.writer(open('/tmp/cadre_dev.csv', 'w', newline=''))
+for r in rows: w.writerow(r)
+sys.stderr.write(f"CA DRE subdivider: {len(rows)} unique SoCal developers -> /tmp/cadre_dev.csv\n")

← ba624d2 pipeline: DFPI escrow+CFL scraper (3532 rows) + attorney reu  ·  back to Rentv Licensed Targets  ·  fix: CA DRE subdivider raw json.dumps; 459 CA developers loa 60ac06c →