9d49a99916
Chrome extension for PokemonCenter monitoring with Discord notifications. Includes Python scripts for Target monitoring. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
76 lines
1.8 KiB
Python
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
|