README for coupons
This project exists to make it easy to query the current sale papers for select grocery stores, including specifically Publix. Frontends include cli and a webapp (python flask).
Upstream
This project's upstream is at https://bgstack15.ddns.net/cgit/coupons.
Features
- simple cli
- simple wsgi web app with minimal javascript
- caching of results for faster lookups during the same day
Alternatives
Visiting https://southernsavers.com manually, or each store's website.
I previously started using selenium (see aux/ads1.py in initial commit) but that was not necessary.
Reason for existence
To simplify and automate searching for items currently on sale.
Using
Command line interface
Basic usage is pretty simple. You need to specify a store at a minimum. When the script visits the webpage, it will cache the file to $XDG_CACHE_DIR/coupons/
to reduce the amount of work needed during the same day.
./coupons.py --store "publix" --search "candy"
To use standard input from a fully-cached javascript response from the website, you could run this.
<~/.cache/coupons/publix_2022-09-01.json ./coupons.py --stdin --clean --search "candy" --pretty
An already-cleaned json file would not need the --clean flag. But the cached values are the exact javascript+json payload from the server.
See also ./coupons.py --help
.
Web app
Run a simple dev environment.
FLASK_APP=coupons_web.py FLASK_DEBUG=True flask run --host='0.0.0.0'
For a more robust production environment, drop the extra/wsgi-coupons.conf
apache config into your apache httpd conf directory and configure it as documented in there.
Visiting the web app with curl
$ curl http://d2-03a/coupons/search/dog --header 'Accept: application/json' ; printf '\n'
[{"publix": {"Publix Weekly Ad: 9/7-9/13 or 9/8-9/14": {"Buy One Get Ones": ["Healthy Hide Good'n Fun Dog Treats Triple Flavor Ribs or Wings, 12 oz, at $11.99 <small>($5.99)</small>"]}, "Unadvertised Deals: 9/7-9/13": {"Pet Care": ["Blue Dry Dog Food, 5 lb, $14.99"]}, "Extra Savings Flyer: 8/27-9/9": {"Meat": ["Greenfield Natural Meat Co. Bratwurst 12 oz, Hot Dogs 13 oz or Lunchmeat, 7 oz, $4"]}}}, {"ingles": {"Ingles Ad & Coupons: 9/7-9/13": {"Meat": ["Gwaltney Hot Dogs, 12 oz, $1.48"]}}}, {"food lion": {"Food Lion Ad & Coupons: 9/7-9/13": {"Pet Care": ["Rachael Ray Nutrish Dry Dog Food, 5.5-6 lb, $10.99"]}}}]
$ curl -X POST http://d2-03a/coupons/search/ --data 'mayo' --header 'Accept: application/json' ; printf '\n'
[{"publix": {"Publix Weekly Ad: 9/7-9/13 or 9/8-9/14": {"Buy One Get Ones": ["Duke's Mayonnaise, 30-32 oz, at $5.23 <small>($3.11)</small>", "Hellmann's Mayonnaise, 15-20 oz, at $5.75 <small>($2.87)</small>"]}, "Extra Savings Flyer: 9/10-9/23": {"Grocery": ["Hellmann's Mayonnaise, 24-30 oz, $3.99", "Hellmann's Mayonnaise, Spicy Mayonnaise or Vegan Dressing & Spread, 11.5 oz, $3", "Primal Kitchen Mayonnaise, 12 oz, $8.99", "Sir Kensington's Special Sauce or Chipotle Mayonnaise, 12 oz, $4"]}}}]
The API accepts a few URL parameters, including &date=YYYY-MM-DD
to use that day's cached results (it does not time travel for you) and ?nocache=1
.
Improvements
- Add flask-correct logger mechanisms?
Dependencies
For the web app:
- apache with
mod_wsgi
- python3-flask
For AlmaLinux 8:
- python3-flask
- python3-mod_wsgi
- httpd
Building or changing
Only a few stores are currently supported. The southernsavers.com website lists other stores that are probably drop-in capable. To learn the widgets.json path needed, use Developer Tools in a web browser to capture the full widgets.json path and add it to the stores_url dict.
References
- Developer Tools in Firefox
- stackbin