
demo scraper — the scheduler keeps ticking every round exactly as it would in production, it just never makes a real request. That means you can leave the dashboard running: prices drift on their own, alerts fire on schedule, and nothing turns red just because it couldn't reach a fake sample site..env.example:DATABASE_URL sqlite:///./pricewatch.db Swap in a Postgres connection string to change database CHECK_INTERVAL_MINUTES 30 Interval between full scrape rounds ALERT_DROP_PERCENT 5 Alert when a drop exceeds this percentage ALERT_WEBHOOK_URL empty WeCom / DingTalk / Slack / Discord bot URL — leave blank to log alerts without sending them REQUEST_TIMEOUT 20 Per-request timeout, in secondsBaseScraper subclass and registering it with a single line in the registry — scheduling, storage, and alerting don't change.DATABASE_URL to move to Postgres, and swap APScheduler for Celery once volume actually calls for it./docs — you can call every endpoint straight from the browser:GET /api/products List products with current price, % change, and history POST /api/products Add a product (scrapes it immediately) PATCH /api/products/{id} Update name, selector, target price, active state DELETE /api/products/{id} Delete a product and its history POST /api/products/{id}/check Scrape once, right now GET /api/alerts Recent alert history POST /api/notify/test Send a test message to the configured webhook GET /api/stats Dashboard summary metricsMyShopScraper() to _REGISTRY in app/scrapers/registry.py and you're done.robots.txt and terms of service before scraping. This project defaults to serial checks per product with a global concurrency cap of 5, built for low-frequency price monitoring — it's not meant for high-frequency, large-scale scraping.Posted Jul 27, 2026
Designed and built a production-ready monitoring platform with pluggable scrapers, scheduled checks, price history, failure visibility, and webhook alerts.