← back to Commercialrealestate
enrich-condo-brokers: record ALL license numbers per listing (multi-agent listingAgents capture, not just [0]) + hook every agent DRE# into its full CA DRE record (cached, $0)
fcd24a8dddf8107849b72a6fc946cc9a985e45ab · 2026-08-03 10:53:25 -0700 · Steve Abrams
Files touched
M scripts/enrich-condo-brokers.js
Diff
commit fcd24a8dddf8107849b72a6fc946cc9a985e45ab
Author: Steve Abrams <steve@designerwallcoverings.com>
Date: Mon Aug 3 10:53:25 2026 -0700
enrich-condo-brokers: record ALL license numbers per listing (multi-agent listingAgents capture, not just [0]) + hook every agent DRE# into its full CA DRE record (cached, $0)
---
scripts/enrich-condo-brokers.js | 44 ++++++++++++++++++++++++++++++++---------
1 file changed, 35 insertions(+), 9 deletions(-)
diff --git a/scripts/enrich-condo-brokers.js b/scripts/enrich-condo-brokers.js
index 544d465..14d2ddd 100644
--- a/scripts/enrich-condo-brokers.js
+++ b/scripts/enrich-condo-brokers.js
@@ -54,16 +54,32 @@ function extractBroker(raw) {
// Redfin embeds the listing state as an ESCAPED JSON string (\"listingAgents\":[...]) inside the
// page, so normalize \" -> " before matching. Harmless for our field extraction.
const html = String(raw).replace(/\\"/g, '"');
- // Richest block: "listingAgents":[{"agentInfo":{"agentName":"..."},"brokerName":"...","license":"...","breNumber":"..."}]
- const la = html.match(/"listingAgents":\s*\[\s*\{(.*?)\}\s*\]/s);
+ // Record EVERY license number on the listing (Steve 2026-08-03): the listingAgents array carries
+ // the primary listing agent AND any co-listing agent, each with its own name/brokerName/license.
+ // Capture the full array, split into agent objects (one level of nesting = agentInfo), and pull a
+ // {name, firm, dre} from each — not just [0]. Primary stays in the flat fields for back-compat.
+ const la = html.match(/"listingAgents":\s*\[(.*?)\]/s);
if (la) {
- const blk = la[1];
- const an = blk.match(/"agentName":"([^"]{1,80})"/);
- const bn = blk.match(/"brokerName":"([^"]{1,120})"/);
- const lic = blk.match(/"(?:license|breNumber)":"(\d{6,8})"/);
- if (an && an[1] && !/^\s*$/.test(an[1])) out.broker_name = an[1].trim();
- if (bn && bn[1]) out.firm_name = bn[1].trim();
- if (lic) out.broker_dre = lic[1];
+ const objs = la[1].match(/\{[^{}]*(?:\{[^{}]*\}[^{}]*)*\}/g) || [];
+ const agents = [];
+ const seen = new Set();
+ for (const blk of objs) {
+ const an = blk.match(/"agentName":"([^"]{1,80})"/);
+ const bn = blk.match(/"brokerName":"([^"]{1,120})"/);
+ const lic = blk.match(/"(?:license|breNumber)":"(\d{6,8})"/);
+ const a = {};
+ if (an && an[1].trim()) a.name = an[1].trim();
+ if (bn && bn[1].trim()) a.firm = bn[1].trim();
+ if (lic) a.dre = lic[1];
+ const k = a.dre || a.name;
+ if ((a.name || a.dre) && k && !seen.has(k)) { seen.add(k); agents.push(a); }
+ }
+ if (agents.length) {
+ out.agents = agents; // ALL license-bearing agents
+ if (agents[0].name) out.broker_name = agents[0].name; // primary (back-compat)
+ if (agents[0].firm) out.firm_name = agents[0].firm;
+ if (agents[0].dre) out.broker_dre = agents[0].dre;
+ }
}
// Fallback flat fields near the top of the page state.
if (!out.broker_name) { const m = html.match(/"listingAgentName":"([^"]{1,80})"/); if (m && m[1].trim()) out.broker_name = m[1].trim(); }
@@ -178,6 +194,16 @@ async function main() {
else gotBroker++;
let dre = null;
if (b.broker_dre) { dre = await hookDre(b.broker_dre, dreCache); if (dre && dre.dre_status) gotDre++; }
+ // Hook EVERY license number on the listing into its full CA DRE record (Steve: record all
+ // license numbers, always hook the full list). DRE lookups are $0/local and cached, so
+ // resolving co-agents adds no cost; the primary reuses the record already fetched above.
+ if (Array.isArray(b.agents)) {
+ for (const a of b.agents) {
+ if (!a.dre) continue;
+ const d = (a.dre === b.broker_dre) ? dre : await hookDre(a.dre, dreCache);
+ if (d) a.dre_record = d;
+ }
+ }
brokers[c.id] = { id: c.id, address: c.address, city: c.city, ...b, dre: dre || undefined, fetched_at: new Date().toISOString(), http: status };
fs.writeFileSync(BROKERS, JSON.stringify(brokers, null, 1));
process.stdout.write(`\r ${done}/${targets.length} broker:${gotBroker} dre:${gotDre} blocked:${blocked.length} `);
← a06fde2 detail-modal drill enrichment (index/sales/mls): index broke
·
back to Commercialrealestate
·
record all license numbers on every listing (display): email 3a9480d →