← back to Rentv Licensed Targets

specs/attorneys.md

15 lines

# Attorneys (RE) — access spec  [discovery: COMPLETE 2026-07-31]

## Primary path = reuse existing local infra ($0, no new CA scraping)
- Project: `~/Projects/lawyer-directory-builder`; DB `lawyer_professional_directory` (local PG, /tmp socket) — **separate from dw_unified**.
- **89,390 attorneys / 52,764 Active**; ~**21,700 Active in SoCal ZIPs** (900–935 = LA/OC/Riverside/SB/SD/Ventura).
- Proven scraper `src/ingest/calbar_full_scrape.ts` (undici fetch of `apps.calbar.ca.gov/attorney/Licensee/Detail/{barNumber}`, regex parse, no browser/captcha, `--resume` checkpoint). Fields: name, bar_number (UNIQUE), license_status, firm_name, address, city/state/zip, phone. No email, no practice area.

## "CRE attorney" approximation
- CalBar publishes **NO practice area** (`primary_practice_area` = 0/89,390) and Real Estate is NOT a Certified Legal Specialist field → no native filter.
- **CA proxy:** on Active + SoCal-ZIP set, `firm ~* 'real estate|realty|commercial|property|development|title|escrow|land use|zoning'` → ~55 high-precision core; widen via firm-website scrape / broker-roster cross-match (project has `discover_websites.ts`, `firm_website_contacts.ts`, `ad_signals.ts`).
- **AZ:** azbar.org member directory HAS a real-estate practice + Maricopa-county filter → filter at source (no proxy). Needs one Playwright submission to capture the `/search-results` POST params, then replay+paginate. Basic search not login-walled.

## Land in dw_unified staging `rentv_licensed_targets` (role='Attorney', source ca_state_bar/az_state_bar).
## Gates: local mirror ETL = safe; AZ Playwright pass = trivial paid, run polite + log; canonical dw_unified apply + prod console feed = gated.