Files
pokemon-stock-checker/scrapers/base.py
T
mmcghen 9d49a99916 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>
2026-03-24 12:39:09 -04:00

76 lines
1.8 KiB
Python

"""
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