Pokemon Stock Monitor - Initial commit
Chrome extension for PokemonCenter monitoring with Discord notifications. Includes Python scripts for Target monitoring. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,75 @@
|
||||
"""
|
||||
Base scraper class with common functionality
|
||||
"""
|
||||
|
||||
import logging
|
||||
from abc import ABC, abstractmethod
|
||||
from dataclasses import dataclass
|
||||
from typing import List, Optional
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
@dataclass
|
||||
class Product:
|
||||
"""Represents a product listing"""
|
||||
name: str
|
||||
url: str
|
||||
price: Optional[str]
|
||||
in_stock: bool
|
||||
image_url: Optional[str] = None
|
||||
site: str = ""
|
||||
product_id: Optional[str] = None # Unique identifier for tracking
|
||||
|
||||
def __hash__(self):
|
||||
return hash(self.url)
|
||||
|
||||
def __eq__(self, other):
|
||||
if isinstance(other, Product):
|
||||
return self.url == other.url
|
||||
return False
|
||||
|
||||
|
||||
class BaseScraper(ABC):
|
||||
"""Base class for site-specific scrapers"""
|
||||
|
||||
site_name: str = "unknown"
|
||||
|
||||
@abstractmethod
|
||||
def scrape_category_page(self, url: str) -> List[Product]:
|
||||
"""
|
||||
Scrape a category/search page and return all products found
|
||||
|
||||
Args:
|
||||
url: URL of the category page
|
||||
|
||||
Returns:
|
||||
List of Product objects
|
||||
"""
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def check_product_stock(self, product_url: str) -> tuple[bool, Optional[str]]:
|
||||
"""
|
||||
Check if a specific product is in stock
|
||||
|
||||
Args:
|
||||
product_url: URL of the product page
|
||||
|
||||
Returns:
|
||||
Tuple of (is_in_stock, price)
|
||||
"""
|
||||
pass
|
||||
|
||||
def filter_by_keywords(self, products: List[Product], keywords: List[str]) -> List[Product]:
|
||||
"""Filter products by keywords in name"""
|
||||
if not keywords:
|
||||
return products
|
||||
|
||||
filtered = []
|
||||
for product in products:
|
||||
name_lower = product.name.lower()
|
||||
if any(kw.lower() in name_lower for kw in keywords):
|
||||
filtered.append(product)
|
||||
|
||||
return filtered
|
||||
Reference in New Issue
Block a user