diff --git a/main.py b/main.py new file mode 100644 index 0000000..ee73350 --- /dev/null +++ b/main.py @@ -0,0 +1,187 @@ + +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) +