Analysis

Turning raw lots into a catalog.

The hard part isn't scraping a price — it's deciding which bottle it belongs to, keeping stats fresh, and exposing history in a way that's useful on a chart and in a CSV download.

30,324
Active bottles
1,351,454
Price rows
1,719
Market stat periods
3
Export CSV files

Bottle normalization

The normalization pipeline matches incoming titles to existing bottles via normalized names and aliases, or creates new bottle records when no match exists. Categories (bourbon, scotch, Irish, etc.) are inferred from title patterns.

bottles table

Canonical catalog with cached aggregates: price_count, avg_price, min/max, last sale, trend direction.

bottle_aliases

Alternate spellings and retailer-specific titles mapped to one bottle ID — critical when the same expression appears across six auction houses.

USD normalization

Every price stored in original currency plus price_usd for cross-source comparison and charting.

Price intelligence on the site

FeatureImplementationUser-facing page
Price history chartsPriceService — daily / weekly / monthly aggregation/bottles/{id}
Trending bottlesRecent activity scoring on price inserts/trending
Market overviewmarket_stats monthly auction volumes/market
Brand browseDistinct brands with category filters/brands
SearchPostgreSQL full-text + autocomplete API/search
CSV / JSON exportAuthenticated export routes/api/export

Market statistics

Monthly aggregates per auction house — mean winning bid, lot counts, trading volume — imported from Kaggle seed data and extended as live scrapers add new hammer prices.

market_stats
├── auction_name, auction_slug
├── period_date
├── winning_bid_min / max / mean
├── trading_volume
└── lots_count

Maintenance tasks

Celery beat runs background jobs beyond scraping:

  • refresh_bottle_stats — recomputes cached min/max/avg on bottles after bulk imports
  • Cleanup tasks — old scrape run records, stale session data
  • Export scriptsexport_dataset.sh → Hugging Face + Kaggle via shared dataset cards

Open dataset page →