/
zimaaadev
/
Parser
Обзор
Документация
Войти
/
zimaaadev
/
Parser
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
Аналитика
Безопасность
master
bot/utils/database.py
154 строки
6 KB
zimaaadev
Работает парсер ЯН, работает гео, но не видит "зеленку". Нужно подключить Яндекс. База развернута на удаленном сервере
22 дек 2025, 14:03
22 дек 2025, 14:03
67f0a61
Код
Авторство
О чём код?
import asyncpg import logging import os logger = logging.getLogger(__name__) # Настройки подключения к PostgreSQL DB_HOST = os.getenv("DB_HOST", "82.202.142.33") DB_PORT = int(os.getenv("DB_PORT", 5432)) DB_NAME = os.getenv("DB_NAME", "realty_db") DB_USER = os.getenv("DB_USER", "admin") DB_PASS = os.getenv("DB_PASS") # Глобальный пул соединений pool = None async def init_db(): """ Инициализация пула соединений и создание таблицы items. Вызывается один раз при старте бота. """ global pool try: pool = await asyncpg.create_pool( host=DB_HOST, port=DB_PORT, database=DB_NAME, user=DB_USER, password=DB_PASS, min_size=1, max_size=10, command_timeout=60, ) logger.info("✅ Подключение к PostgreSQL установлено") # Создаём таблицу async with pool.acquire() as conn: await conn.execute(""" CREATE TABLE IF NOT EXISTS items ( id SERIAL PRIMARY KEY, avito_id TEXT UNIQUE NOT NULL, title TEXT NOT NULL, price INTEGER, price_per_m2 TEXT, url TEXT NOT NULL, location TEXT, street TEXT, house TEXT, description TEXT, published_at TEXT, seller TEXT, house_type TEXT, sale_type TEXT, price_negotiable BOOLEAN DEFAULT FALSE, documents_verified BOOLEAN DEFAULT FALSE, image_url TEXT, is_new BOOLEAN DEFAULT FALSE, district TEXT, lat REAL, lng REAL, city TEXT, source TEXT, parsed_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ); """) # Индексы await conn.execute("CREATE INDEX IF NOT EXISTS idx_avito_id ON items(avito_id);") await conn.execute("CREATE INDEX IF NOT EXISTS idx_city ON items(city);") await conn.execute("CREATE INDEX IF NOT EXISTS idx_price ON items(price);") await conn.execute("CREATE INDEX IF NOT EXISTS idx_parsed_at ON items(parsed_at);") logger.info("✅ Таблица items и индексы готовы") except Exception as e: logger.error(f"❌ Ошибка инициализации базы данных: {e}") raise async def is_listing_exists(avito_id: str) -> bool: """ Проверяет, существует ли объявление по avito_id. """ if not pool: logger.error("❌ Пул соединений не инициализирован") return False try: async with pool.acquire() as conn: result = await conn.fetchval("SELECT 1 FROM items WHERE avito_id = $1", avito_id) return result is not None except Exception as e: logger.error(f"❌ Ошибка при проверке существования объявления {avito_id}: {e}") return False async def save_listing(item: dict): """ Сохраняет объявление в БД. Использует ON CONFLICT DO NOTHING по avito_id. """ print("✅ Я — НОВАЯ ВЕРСИЯ save_listing!") # ← Это должно появиться в логе if not pool: logger.error("❌ Пул соединений не инициализирован") return try: async with pool.acquire() as conn: values = ( item.get("avito_id"), item.get("title"), item.get("price"), item.get("price_per_m2"), item.get("url"), item.get("location"), item.get("street"), item.get("house"), item.get("description"), item.get("published_at"), item.get("seller"), item.get("house_type"), item.get("sale_type"), item.get("price_negotiable", False), item.get("documents_verified", False), item.get("image_url"), item.get("is_new", False), item.get("district"), item.get("lat"), item.get("lng"), item.get("city"), item.get("source"), ) print(f"📡 SQL: INSERT INTO items (...) VALUES ({', '.join(['$'+str(i) for i in range(1, 23)])})") print(f"🔢 Количество значений: {len(values)}") print(f"📋 Значения: {values}") print(f"🔍 Тип каждого значения: {[type(v).__name__ for v in values]}") await conn.execute(""" INSERT INTO items ( avito_id, title, price, price_per_m2, url, location, street, house, description, published_at, seller, house_type, sale_type, price_negotiable, documents_verified, image_url, is_new, district, lat, lng, city, source ) VALUES ( $1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18, $19, $20, $21, $22 ) ON CONFLICT (avito_id) DO NOTHING; """, *values) logger.info(f"💾 Сохранено в БД: {item.get('title')} — {item.get('price', 'N/A')} ₽") except Exception as e: logger.error(f"❌ Ошибка при сохранении объявления {item.get('avito_id')}: {e}")