Better Price is a Django app that lets you search and compare e-book prices at any online bookstore. It is based on real-time web data scraping.
AioHttp, Django, Celery, Redis, PostgreSQL, Channels, Django Rest Framework and Docker.
Python 3.10 or higher
Docker
- Clone the project
git clone https://github.com/MWasile/better_price
- Go to the project directory
cd better_price
-
Based on env/.evn-default create your own .env file
-
Start the server
docker compose up
- Search for e-books.
- Search for e-books.
- Visit Dashboard.
- Check your search history.
- Set email alert for a price based on user input.
Create your bookstores class in async_scraper.py
class NewBookstores:
BOOKSTORE_URL = '' # bookstores url
ALL_EBOOK_CONTAINER = '' # queryselector to main container with e-books on page.
EBOOK_CONTAINER = '' # queryselector to single e-book container
EBOOK_DETAILS = {
#example
'author': {'qs': 'a.smartAuthor', 'type': 'text'},
'title': {'qs': '.ta-product-title', 'type': 'text'},
'price': {'qs': '.price.ta-price-tile', 'type': 'decimal'},
'jpg': {'qs': '.lazy', 'type': 'attribute', 'attr': 'lazy-img'},
'url': {'qs': '.seoTitle', 'type': 'rel', 'attr': 'href', 'base': 'https://www.empik.com'}
}
EBOOK_DETAILS represent data saved in database. Put your queryselector and choose type:
# support option:
'text' -> get text from queryselector.
'decimal' -> get price as decimal from queryselector.
'attribute' -> get value from tag attribute.
'rel' -> join realitve links with 'base'
Create your init only with future user input, next add your function for creating url.
def __init__(self, user_input):
self.user_input = user_input
self.bookstores_url = self.get_url()
def get_url(self):
#example
if len(self.user_input.split()) < 2:
return ''.join([self.BOOKSTORE_URL, self.user_input])
return ''.join([self.BOOKSTORE_URL, '%20'.join(self.user_input.split())])
add your class to settings.py
SCRAPER_BOOKSTORES = [
# ...
'NewBookstores',
# ...
]