From 908e4749169296f135f5338019437fa641c7b349 Mon Sep 17 00:00:00 2001 From: wuliaozhiji Date: Mon, 28 Feb 2022 21:17:36 -0500 Subject: [PATCH] [+] Stock tracking bot --- requirements.txt | 2 + src/BestbuyGpuValueCalculator.js | 2 +- src/StockTrackingBot.py | 92 +++++++++++++++++++++++++++++++- 3 files changed, 94 insertions(+), 2 deletions(-) diff --git a/requirements.txt b/requirements.txt index e69de29..8bc94ab 100644 --- a/requirements.txt +++ b/requirements.txt @@ -0,0 +1,2 @@ +python-telegram-bot +selenium==4.1.2 \ No newline at end of file diff --git a/src/BestbuyGpuValueCalculator.js b/src/BestbuyGpuValueCalculator.js index afa4459..7394963 100644 --- a/src/BestbuyGpuValueCalculator.js +++ b/src/BestbuyGpuValueCalculator.js @@ -6,7 +6,7 @@ // @author Hykilpikonna // @license MIT // @supportURL https://github.com/hykilpikonna/GraphicsCardScripts -// @match https://www.bestbuy.ca/en-ca/collection/graphics-cards-with-nvidia-chipset/349221?icmp=computing_evergreen_graphics_cards_category_listing_category_icon_shopby_nvidia +// @match https://www.bestbuy.ca/en-ca/collection/graphics-cards-with-nvidia-chipset/349221 // @icon https://www.google.com/s2/favicons?sz=64&domain=bestbuy.ca // @require http://code.jquery.com/jquery-3.6.0.min.js // @grant none diff --git a/src/StockTrackingBot.py b/src/StockTrackingBot.py index 09d65dc..65351f0 100644 --- a/src/StockTrackingBot.py +++ b/src/StockTrackingBot.py @@ -1,2 +1,92 @@ +import os +import time + +import requests +from selenium.webdriver import Chrome +from selenium.webdriver.chrome.options import Options +from selenium.webdriver.common.by import By + +# Config +# Price increase ratio threshold (ignore everything higher than this ratio) +INCR_MAX = 0.2 +# Telegram chat ID that receives update messages (could be a channel in @channel_id format) +# TG_RECEIVER = 1770239825 +TG_RECEIVER = '@toronto_bestbuy_gpu' +# Telegram bot token +TG_TOKEN = os.environ['TG_TOKEN'] + +# Constants +CSS = By.CSS_SELECTOR +MODELS = [ + ['3060 ti', 400, 132], + ['3070 ti', 600, 167], + ['3080 ti', 1200, 233], + ['3050', 250, 73], + ['3060', 330, 98], + ['3070', 500, 154], + ['3080', 700, 204], + ['3090', 1500, 236], +] +USD_TO_CAD = 1.27 +AVAIL_TABLE: dict[str, bool] = {} + + +def parse_page(browser: Chrome): + # Parse page + for item in browser.find_elements(By.CLASS_NAME, 'x-productListItem'): + title = item.find_element(CSS, 'div[data-automation="productItemName"]').get_attribute('innerHTML') + + # Check availability + avail = item.find_elements(CSS, 'div[data-automation="store-availability-messages"] span[data-automation="store-availability-checkmark"]') + + # Not available, check if it was previously available + if len(avail) == 0: + if title in AVAIL_TABLE: + # TODO: Feedback + del AVAIL_TABLE[title] + continue + + # Get price + price = item.find_element(CSS, 'div[data-automation="product-pricing"] > span > div').get_attribute('innerHTML') + price = round(float(price.replace(',', '')[1:])) + price_usd = price / USD_TO_CAD + + # Find model + lower = title.lower() + model = [c for c in MODELS if c[0] in lower] + if not model: + continue + model = model[0] + + # Calculate price increase + price_incr = (price_usd - model[1]) / model[1] + value = model[2] / price_usd * 100 + + # Check incr threshold + if price_incr > INCR_MAX: + print(' '.join(title.split()[:2]), f'is in stock but price increase {price_incr * 100:.0f}% ' + f'is larger than defined threshold.') + continue + + # Available and meets threshold criteria, notify user + AVAIL_TABLE[title] = True + + print(model) + print(title) + + if __name__ == '__main__': - pass \ No newline at end of file + web_options = Options() + # web_options.headless = True + + browser = Chrome(options=web_options) + browser.get('https://www.bestbuy.ca/en-ca/collection/graphics-cards-with-nvidia-chipset/349221') + + parse_page(browser) + browser.close() + + # Refresh indefinitely + # while True: + # parse_page(browser) + # time.sleep(5) + # browser.refresh()