← back to Commercialrealestate
Tighten live-comps units parse
5b97a7703aa2e579f049c5835c2a97e1536d932f · 2026-06-21 17:52:46 -0700 · Steve
- anchor units regex (\b, 1-3 digits, cap 500) so a 5-digit zip can't be read as a unit count
- prefer Crexi structured unit fields over description text
- $/unit plausibility gate: suppress implausibly-low-per-unit counts (junk source data)
- verified live: bogus '91 units @ $35k/unit' now suppressed; legit counts retained
Files touched
M scripts/live-comps-bb.js
Diff
commit 5b97a7703aa2e579f049c5835c2a97e1536d932f
Author: Steve <steve@designerwallcoverings.com>
Date: Sun Jun 21 17:52:46 2026 -0700
Tighten live-comps units parse
- anchor units regex (\b, 1-3 digits, cap 500) so a 5-digit zip can't be read as a unit count
- prefer Crexi structured unit fields over description text
- $/unit plausibility gate: suppress implausibly-low-per-unit counts (junk source data)
- verified live: bogus '91 units @ $35k/unit' now suppressed; legit counts retained
---
scripts/live-comps-bb.js | 17 ++++++++++++++---
1 file changed, 14 insertions(+), 3 deletions(-)
diff --git a/scripts/live-comps-bb.js b/scripts/live-comps-bb.js
index f3e1b24..aab5230 100644
--- a/scripts/live-comps-bb.js
+++ b/scripts/live-comps-bb.js
@@ -44,7 +44,18 @@ const URL = `https://www.crexi.com/properties/CA/${citySlug}/${SLUG}`;
url: a.urlSlug ? 'https://www.crexi.com/properties/' + id + '/' + a.urlSlug : 'https://www.crexi.com/properties/' + id,
price: '$' + Number(price).toLocaleString(),
cap: a.capRate ? a.capRate + '% Cap' : null,
- units: (String(a.description || '').match(/(\d+)\s*Units?/i) || [])[0] || null,
+ units: (() => {
+ let n = null;
+ for (const k of ['numberOfUnits', 'units', 'unitCount', 'numUnits', 'totalUnits']) {
+ if (typeof a[k] === 'number' && a[k] >= 1 && a[k] <= 500) { n = a[k]; break; }
+ }
+ // Crexi description format: "Multifamily | 4 Units" — anchored, capped, never swallows a zip
+ if (n == null) { const m = String(a.description || '').match(/(?:\|\s*)?\b(\d{1,3})\s*units?\b/i); if (m) n = +m[1]; }
+ if (!n || n < 1 || n > 500) return null;
+ // Plausibility gate: an implausibly low $/unit means the source count is junk -> suppress it.
+ if (price && price / n < 50000) return null;
+ return n + (n === 1 ? ' Unit' : ' Units');
+ })(),
sf: null, city: loc.city, state: (loc.state && loc.state.code) || 'CA'
});
}
@@ -73,8 +84,8 @@ const URL = `https://www.crexi.com/properties/CA/${citySlug}/${SLUG}`;
title: (a.innerText || '').replace(/\s+/g, ' ').trim().slice(0, 80) || (href.split('/properties/')[1] || href).slice(0, 50),
url: href, price,
cap: (txt.match(/(\d+\.?\d*)%\s*Cap/i) || [])[0] || null,
- units: (txt.match(/(\d+)\s*Unit/i) || [])[0] || null,
- sf: (txt.match(/([\d,]+)\s*SF/i) || [])[0] || null
+ units: (txt.match(/\b(\d{1,3})\s*units?\b/i) || [])[0] || null,
+ sf: (txt.match(/\b([\d,]{2,7})\s*SF\b/i) || [])[0] || null
});
}
return { comps: res.slice(0, 8), challenge, anchorCount: anchors.length, title: document.title };
← 89f1ab2 Live comps -> Browserbase/Crexi (drop Exa dependency)
·
back to Commercialrealestate
·
Add daily morning-report generator (top 10 SFV CRE opportuni de42fa5 →