Загрузка данных


import os
import re
import json
import time
import requests
from bs4 import BeautifulSoup
from playwright.sync_api import sync_playwright

# ==================== НАСТРОЙКИ TELEGRAM ====================
TELEGRAM_BOT_TOKEN = "ВАШ_ТОКЕН_ОТ_BOTFATHER"
TELEGRAM_CHAT_ID = "ВАШ_CHAT_ID"

# Если доступ к api.telegram.org требует прокси, укажите его здесь:
# Например: TG_PROXY = "http://127.0.0.1:1080"
TG_PROXY = None

# ==================== НАСТРОЙКИ ФИЛЬТРАЦИИ ====================
MAX_PRICE = 2500

# Ссылка на категорию "Головные уборы", поиск "gatta", сортировка "По дате"
AVITO_URL = "https://www.avito.ru/rossiya/odezhda_obuv_aksessuary/aksessuary/golovnye_ubory-ASgBAgICAUT8AtgM?q=gatta&s=104"

CAP_KEYWORDS = ["кепк", "бейсболк", "снепбек", "snapback", "тракер", "trucker", "cap"]
STOP_WORDS = ["колготк", "чулк", "носк", "лосин", "белье", "леггинс", "трусы", "майка", "топ", "платье"]

CHECK_INTERVAL = 60
SEEN_FILE = "seen_items.json"


def send_telegram_photo(caption: str, photo_bytes: bytes):
    """Отправка фото с описанием в Telegram."""
    url = f"https://api.telegram.org/bot{TELEGRAM_BOT_TOKEN}/sendPhoto"
    data = {
        "chat_id": TELEGRAM_CHAT_ID,
        "caption": caption,
        "parse_mode": "HTML"
    }
    files = {
        "photo": ("card.png", photo_bytes, "image/png")
    }
    proxies = {"http": TG_PROXY, "https": TG_PROXY} if TG_PROXY else None
    try:
        response = requests.post(url, data=data, files=files, timeout=25, proxies=proxies)
        if response.status_code != 200:
            print(f"[TG ERROR] Статус: {response.status_code}, Ответ: {response.text}")
    except Exception as e:
        print(f"[TG ERROR] Сбой отправки фото: {e}")


def send_telegram_text(text: str):
    """Отправка простого текстового сообщения (например, о запуске)."""
    url = f"https://api.telegram.org/bot{TELEGRAM_BOT_TOKEN}/sendMessage"
    payload = {
        "chat_id": TELEGRAM_CHAT_ID,
        "text": text,
        "parse_mode": "HTML"
    }
    proxies = {"http": TG_PROXY, "https": TG_PROXY} if TG_PROXY else None
    try:
        requests.post(url, json=payload, timeout=12, proxies=proxies)
    except Exception as e:
        print(f"[TG ERROR] Сбой отправки текста: {e}")


def load_seen() -> set:
    if os.path.exists(SEEN_FILE):
        try:
            with open(SEEN_FILE, "r", encoding="utf-8") as f:
                return set(json.load(f))
        except Exception:
            return set()
    return set()


def save_seen(seen_ids: set):
    with open(SEEN_FILE, "w", encoding="utf-8") as f:
        json.dump(list(seen_ids), f, ensure_ascii=False, indent=2)


def extract_price(text: str) -> int:
    clean = re.sub(r"[^\d]", "", text)
    return int(clean) if clean else 0


def parse_page(page, seen_ids: set):
    """Ищет подходящие товары и делает скриншот карточки объявления."""
    html_content = page.content()
    soup = BeautifulSoup(html_content, "html.parser")
    items = soup.find_all("div", {"data-marker": "item"})

    if not items:
        return

    for item in items:
        item_id = item.get("data-item-id")
        if not item_id or item_id in seen_ids:
            continue

        title_el = item.find("a", {"data-marker": "item-title"})
        if not title_el:
            continue

        title = title_el.get_text(strip=True)
        title_lower = title.lower()
        link = "https://www.avito.ru" + title_el.get("href", "")

        # Цена
        price_meta = item.find("meta", {"itemprop": "price"})
        if price_meta and price_meta.get("content"):
            price = int(price_meta["content"])
        else:
            price_box = item.find("strong")
            price = extract_price(price_box.get_text()) if price_box else 0

        # Фильтры
        has_brand = "gatta" in title_lower
        is_cap = any(kw in title_lower for kw in CAP_KEYWORDS)
        has_stop_word = any(sw in title_lower for sw in STOP_WORDS)

        if has_brand and is_cap and not has_stop_word and 0 < price <= MAX_PRICE:
            caption = (
                f"🧢 <b>Найдена кепка Gatta до {MAX_PRICE} ₽!</b>\n\n"
                f"📌 <b>Товар:</b> {title}\n"
                f"💵 <b>Цена:</b> {price} ₽\n"
                f"🔗 <a href='{link}'>Открыть объявление</a>"
            )
            print(f"[УСПЕХ] Поймали кепку: {title} — {price} ₽")

            # Делаем скриншот карточки через Playwright
            try:
                card_locator = page.locator(f'div[data-marker="item"][data-item-id="{item_id}"]').first
                photo_bytes = card_locator.screenshot()
                send_telegram_photo(caption, photo_bytes)
            except Exception as e:
                print(f"[SCREENSHOT ERROR] Не удалось снять карточку, шлем текстом: {e}")
                send_telegram_text(caption)

        seen_ids.add(item_id)

    save_seen(seen_ids)


def run_bot():
    seen_ids = load_seen()
    print("Запуск мониторинга кепок Gatta со скриншотами...")
    send_telegram_text("🚀 <i>Бот запущен. Мониторинг кепок Gatta со скриншотами активен!</i>")

    with sync_playwright() as p:
        browser = p.chromium.launch(
            headless=False,
            args=["--disable-blink-features=AutomationControlled"]
        )
        context = browser.new_context(
            user_agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36",
            viewport={"width": 1366, "height": 768}
        )
        page = context.new_page()

        print("Загружаем выдачу Авито...")
        page.goto(AVITO_URL, wait_until="domcontentloaded", timeout=45000)
        page.wait_for_timeout(4000)

        while True:
            try:
                page.reload(wait_until="domcontentloaded", timeout=45000)
                # Даем время карточкам и картинкам полностью отрендериться
                page.wait_for_timeout(3500)

                parse_page(page, seen_ids)
                print(f"[OK] Проверка завершена. Следующее обновление через {CHECK_INTERVAL} сек...")
            except Exception as err:
                print(f"[ОШИБКА В ЦИКЛЕ] {err}")

            time.sleep(CHECK_INTERVAL)


if __name__ == "__main__":
    run_bot()