from fastapi import FastAPI, HTTPException, Query from fastapi.middleware.cors import CORSMiddleware # <-- добавлено from pydantic import BaseModel from typing import List, Optional import psycopg2 import psycopg2.extras import uvicorn import json app = FastAPI(title="Parser Data API", description="API для записи данных парсинга в базу данных", version="1.0") app.add_middleware( CORSMiddleware, allow_origins=["*"], # или список разрешенных адресов, например ["http://localhost:8080"] allow_credentials=True, allow_methods=["*"], allow_headers=["*"], ) # Модель для данных, которые приходят в POST class ParsedData(BaseModel): url: str parsed_at: str title: str original_text: str article_date: str status: Optional[bool] = False viewed: Optional[bool] = False other: str category: str translation_text: str short_text: str # Подключение к БД def get_connection(): return psycopg2.connect( dbname="parsed_url", user="postgres", password="qwertyqwerty123123", host="127.0.0.1" ) @app.post("/save_parsed_data", summary="Сохранить данные парсинга") def save_parsed_data(data: ParsedData): conn = None try: conn = get_connection() with conn.cursor() as cur: cur.execute(""" INSERT INTO url (url, parsed_at, title, original_text, article_date, status, viewed, other, category, translation_text, short_text) VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s) ON CONFLICT (url) DO UPDATE SET parsed_at = EXCLUDED.parsed_at, title = EXCLUDED.title, original_text = EXCLUDED.original_text, article_date = EXCLUDED.article_date, status = EXCLUDED.status, viewed = EXCLUDED.viewed, other = EXCLUDED.other, category = EXCLUDED.category, translation_text = EXCLUDED.translation_text, short_text = EXCLUDED.short_text; """, (data.url, data.parsed_at, data.title, data.original_text, data.article_date, data.status, data.viewed, data.other, data.category, data.translation_text, data.short_text)) conn.commit() return {"status": "success", "message": "Данные успешно сохранены"} except Exception as e: if conn: conn.rollback() raise HTTPException(status_code=500, detail=f"Ошибка при сохранении данных: {e}") finally: if conn: conn.close() @app.post("/update_viewed_status", summary="Сохранить данные парсинга") def update_viewed_status(url: str, viewed: bool): """ Обновляет поле 'viewed' записи в БД по заданному URL. """ conn = None try: conn = get_connection() with conn.cursor() as cursor: cursor.execute( """ UPDATE url SET viewed = %s WHERE url = %s """, (viewed, url) ) if cursor.rowcount == 0: # Если запись не найдена raise HTTPException(status_code=404, detail="Запись с указанным URL не найдена") conn.commit() except Exception as e: if conn: conn.rollback() raise HTTPException(status_code=500, detail=f"Ошибка при сохранении данных: {e}") finally: if conn: conn.close() return {"status": "success", "message": "Статус просмотра успешно обновлен"} @app.get("/check_url_exists") def check_url_exists(url: str): """ Проверяет, есть ли указанный URL в базе данных. Возвращает true, если есть, иначе false. """ conn = None try: conn = get_connection() with conn.cursor() as cursor: cursor.execute( "SELECT 1 FROM url WHERE url = %s LIMIT 1", (url,) ) result = cursor.fetchone() return {"exists": bool(result)} except Exception as e: raise HTTPException(status_code=500, detail=f"Ошибка при проверке: {e}") finally: if conn: conn.close() @app.get("/records", summary="Получить записи из БД с пагинацией", response_model=List[ParsedData]) def get_records(offset: int = Query(0, ge=0), limit: int = Query(10, ge=1, le=100)): """ Возвращает записи из таблицы url с учетом offset и limit. """ conn = None try: conn = get_connection() with conn.cursor(cursor_factory=psycopg2.extras.DictCursor) as cur: cur.execute(""" SELECT url, parsed_at, title, original_text, article_date, status, viewed, other, category, translation_text, short_text FROM url ORDER BY parsed_at DESC NULLS LAST OFFSET %s LIMIT %s """, (offset, limit)) rows = cur.fetchall() results = [dict(row) for row in rows] return results except Exception as e: raise HTTPException(status_code=500, detail=f"Ошибка при получении записей из БД: {e}") finally: if conn: conn.close() @app.get("/records_all", summary="Получить все записи из БД + сортирует", response_model=List[ParsedData]) def get_records(): """ Возвращает записи из таблицы url с учетом. """ conn = None try: conn = get_connection() with conn.cursor(cursor_factory=psycopg2.extras.DictCursor) as cur: cur.execute(""" SELECT url, parsed_at, title, original_text, article_date, status, viewed, other, category, translation_text, short_text FROM url ORDER BY (viewed = true) ASC, parsed_at DESC """) rows = cur.fetchall() results = [dict(row) for row in rows] urls = [item['parsed_at'] for item in results] print(urls) return results except Exception as e: raise HTTPException(status_code=500, detail=f"Ошибка при получении записей из БД: {e}") finally: if conn: conn.close() # get_records() # Запуск сервера для теста if __name__ == "__main__": uvicorn.run("main:app", port=8002, reload=True)