← back to Homesonspec
scripts/geocode-permits.sh
48 lines
#!/usr/bin/env bash
# Geocode building_permits via the free US Census batch geocoder (no key, $0).
# 10k-address chunks; marks geo_status ('match'/'nomatch') so unmatched rows don't
# re-loop. LA permits are mostly on existing parcels → high hit rate expected.
# Usage: scripts/geocode-permits.sh <source> <max_chunks> e.g. geocode-permits.sh la 6
set -uo pipefail
DBURL='postgresql://macstudio3@localhost/homesonspec?host=/tmp'
SRC="${1:-la}"; MAXC="${2:-6}"
IN=/tmp/pgeo_in.csv; OUT=/tmp/pgeo_out.csv
c=0; total_match=0
while [ "$c" -lt "$MAXC" ]; do
c=$((c+1))
psql "$DBURL" -tAc "copy (
select id, regexp_replace(address, '\s*(#|apt|ste|unit|bldg).*\$','','i'), city, state, zip
from building_permits
where source='$SRC' and geo_status is null and address is not null and address<>'' and zip is not null
limit 10000
) to stdout with csv" > "$IN"
n=$(wc -l < "$IN" | tr -d ' ')
[ "$n" -eq 0 ] && { echo "chunk $c: nothing left"; break; }
echo "chunk $c: geocoding $n addresses…"
curl -s --max-time 900 --form addressFile=@"$IN" --form benchmark=Public_AR_Current \
"https://geocoding.geo.census.gov/geocoder/locations/addressbatch" -o "$OUT"
python3 - "$OUT" <<'PYEOF'
import csv, sys
mups=[]; nups=[]
for r in csv.reader(open(sys.argv[1])):
if len(r) < 3: continue
hid, ind = r[0], r[2]
if ind == "Match" and len(r) >= 6 and "," in r[5]:
try: lon, lat = (float(x) for x in r[5].split(",")[:2])
except: nups.append(hid); continue
mups.append("update building_permits set lat=%f, lon=%f, geo_status='match' where id='%s';" % (lat, lon, hid))
else:
nups.append(hid)
sql = "begin;\n" + "\n".join(mups)
if nups:
# mark the rest of this batch as attempted so they don't re-loop
ids = ",".join("'%s'" % x.replace("'", "''") for x in nups)
sql += "\nupdate building_permits set geo_status='nomatch' where id in (%s);" % ids
sql += "\ncommit;\n"
open("/tmp/pgeo_up.sql", "w").write(sql)
print(" matched %d / %d" % (len(mups), len(mups) + len(nups)))
PYEOF
psql "$DBURL" -f /tmp/pgeo_up.sql >/dev/null 2>&1
done
echo "geocoded source=$SRC: $(psql "$DBURL" -tAc "select count(*) from building_permits where source='$SRC' and lat is not null;") with coords now."