добавление отслеживания количества выгрузки
All checks were successful
continuous-integration/drone/push Build is passing
All checks were successful
continuous-integration/drone/push Build is passing
This commit is contained in:
@@ -12,7 +12,7 @@ from fastapi.responses import FileResponse
|
||||
|
||||
from config import DOCUMENTS_DIR, APP_TITLE, APP_DESCRIPTION, APP_VERSION
|
||||
from utils import logger
|
||||
from api.schemas import ParserOneRequest, Parserall, Source, DownloadRange
|
||||
from api.schemas import ParserOneRequest, Parserall, Source, DownloadRange, DownloadCountsResponse
|
||||
from parsers import start_pars_one_istochnik, start_pars_two_istochnik, start_pars_all_istochnik
|
||||
import work_parser as wp
|
||||
|
||||
@@ -178,6 +178,13 @@ def setup_routes(app: FastAPI) -> None:
|
||||
except Exception as e:
|
||||
logger.warning(f"Не удалось удалить архив: {e}")
|
||||
|
||||
def mark_as_downloaded():
|
||||
try:
|
||||
wp.mark_articles_as_downloaded(titles_from_db)
|
||||
logger.info(f"Статьи помечены как скачанные: {len(titles_from_db)} записей")
|
||||
except Exception as e:
|
||||
logger.error(f"Ошибка при обновлении download: {e}")
|
||||
|
||||
response = FileResponse(
|
||||
path=archive_path,
|
||||
filename=archive_name,
|
||||
@@ -189,9 +196,27 @@ def setup_routes(app: FastAPI) -> None:
|
||||
response.headers["Access-Control-Expose-Headers"] = "Content-Disposition"
|
||||
|
||||
background_tasks.add_task(cleanup_archive)
|
||||
background_tasks.add_task(mark_as_downloaded)
|
||||
|
||||
return response
|
||||
|
||||
# ==================== Выгрузка (download) ====================
|
||||
|
||||
@app.get("/download_counts", summary="Получить количество статей для выгрузки", response_model=DownloadCountsResponse)
|
||||
async def get_download_counts():
|
||||
"""
|
||||
Возвращает количество статей для каждого поля (tematik, svodka, donesenie, bilutene, status),
|
||||
где значение поля = TRUE и download = FALSE
|
||||
"""
|
||||
return wp.get_download_counts()
|
||||
|
||||
# @app.post("/mark_downloaded", summary="Отметить статьи как скачанные")
|
||||
# async def mark_articles_as_downloaded(titles: List[str]):
|
||||
# """
|
||||
# Обновляет поле download = TRUE для списка заголовков статей
|
||||
# """
|
||||
# return wp.mark_articles_as_downloaded(titles)
|
||||
|
||||
@app.get("/logs", summary="Показать логи")
|
||||
async def get_logs():
|
||||
with open("app.log", "r") as file:
|
||||
|
||||
@@ -32,3 +32,11 @@ class DownloadRange(BaseModel):
|
||||
data_start: str
|
||||
data_finish: str
|
||||
field_name: str = "status"
|
||||
|
||||
|
||||
class DownloadCountsResponse(BaseModel):
|
||||
"""Ответ с количеством статей для выгрузки по каждому полю"""
|
||||
tematik: int
|
||||
svodka: int
|
||||
donesenie: int
|
||||
bilutene: int
|
||||
|
||||
1
main.py
1
main.py
@@ -45,7 +45,6 @@ async def lifespan(app: FastAPI):
|
||||
total_minutes = int(idx * minutes_per_source)
|
||||
scheduled_hour = total_minutes // 60
|
||||
scheduled_minute = total_minutes % 60
|
||||
|
||||
# Для универсального парсера нужно передавать url и promt как аргументы
|
||||
scheduler.add_job(
|
||||
scheduled_parser_universal,
|
||||
|
||||
@@ -52,6 +52,7 @@ def update_bd_and_create_document(
|
||||
data['donesenie'] = False
|
||||
data['bilutene'] = False
|
||||
data['other'] = other
|
||||
data['download'] = False
|
||||
|
||||
# Сохранение в БД через pbd
|
||||
parsed_data = wp.ParsedData(**data)
|
||||
|
||||
@@ -26,6 +26,7 @@ class ParsedData(BaseModel):
|
||||
svodka: Optional[bool] = False
|
||||
donesenie: Optional[bool] = False
|
||||
bilutene: Optional[bool] = False
|
||||
download: Optional[bool] = False
|
||||
other: str
|
||||
category: str
|
||||
translation_text: str
|
||||
@@ -38,8 +39,8 @@ def save_parsed_data_to_db(data: ParsedData):
|
||||
conn = get_connection()
|
||||
with conn.cursor() as cur:
|
||||
cur.execute("""
|
||||
INSERT INTO url (url, parsed_at, title, original_text, article_date, status, viewed, tematik, svodka, donesenie, bilutene, other, category, translation_text, short_text)
|
||||
VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)
|
||||
INSERT INTO url (url, parsed_at, title, original_text, article_date, status, viewed, tematik, svodka, donesenie, download, bilutene, other, category, translation_text, short_text)
|
||||
VALUES (%s, %s, %s, %s, %s, %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,
|
||||
@@ -48,6 +49,7 @@ def save_parsed_data_to_db(data: ParsedData):
|
||||
status = EXCLUDED.status,
|
||||
viewed = EXCLUDED.viewed,
|
||||
tematik = EXCLUDED.tematik,
|
||||
download = EXCLUDED.download,
|
||||
svodka = EXCLUDED.svodka,
|
||||
donesenie = EXCLUDED.donesenie,
|
||||
bilutene = EXCLUDED.bilutene,
|
||||
@@ -55,7 +57,7 @@ def save_parsed_data_to_db(data: ParsedData):
|
||||
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.tematik, data.svodka, data.donesenie, data.bilutene, data.other, data.category, data.translation_text, data.short_text))
|
||||
""", (data.url, data.parsed_at, data.title, data.original_text, data.article_date, data.status, data.viewed, data.tematik, data.svodka, data.donesenie, data.download, data.bilutene, data.other, data.category, data.translation_text, data.short_text))
|
||||
conn.commit()
|
||||
return {"status": "success", "message": "Данные успешно сохранены"}
|
||||
except Exception as e:
|
||||
@@ -68,15 +70,7 @@ def save_parsed_data_to_db(data: ParsedData):
|
||||
|
||||
def get_articles_by_filter(field_name: str, start_date: str, finish_date: str):
|
||||
"""
|
||||
Возвращает список заголовков статей по полю и диапазону дат
|
||||
|
||||
Args:
|
||||
field_name: имя поля (tematik, svodka, donesenie, bilutene, status)
|
||||
start_date: дата начала в формате YYYY-MM-DD
|
||||
finish_date: дата окончания в формате YYYY-MM-DD
|
||||
|
||||
Returns:
|
||||
List[str]: список заголовков (title)
|
||||
Возвращает список заголовков статей по полю и диапазону дат для выгрузки
|
||||
"""
|
||||
conn = get_connection()
|
||||
try:
|
||||
@@ -100,6 +94,54 @@ def get_articles_by_filter(field_name: str, start_date: str, finish_date: str):
|
||||
raise
|
||||
|
||||
|
||||
def get_download_counts():
|
||||
"""
|
||||
Возвращает количество статей для каждого поля, где поле = TRUE и download = FALSE
|
||||
"""
|
||||
conn = get_connection()
|
||||
try:
|
||||
allowed_fields = ['tematik', 'svodka', 'donesenie', 'bilutene']
|
||||
|
||||
with conn.cursor(cursor_factory=RealDictCursor) as cur:
|
||||
counts = {}
|
||||
for field in allowed_fields:
|
||||
cur.execute(f"""
|
||||
SELECT COUNT(*) as count FROM url
|
||||
WHERE {field} = TRUE
|
||||
AND download = FALSE;
|
||||
""")
|
||||
row = cur.fetchone()
|
||||
counts[field] = row['count']
|
||||
|
||||
return counts
|
||||
except Exception as e:
|
||||
print(f"Ошибка в get_download_counts: {e}")
|
||||
raise
|
||||
|
||||
|
||||
def mark_articles_as_downloaded(titles: list):
|
||||
"""
|
||||
Обновляет download = TRUE для списка заголовков
|
||||
"""
|
||||
if not titles:
|
||||
return {"message": "Список заголовков пуст", "updated_rows": 0}
|
||||
|
||||
conn = get_connection()
|
||||
try:
|
||||
with conn.cursor() as cur:
|
||||
cur.execute("""
|
||||
UPDATE url
|
||||
SET download = TRUE
|
||||
WHERE title = ANY(%s);
|
||||
""", (titles,))
|
||||
updated_rows = cur.rowcount
|
||||
conn.commit()
|
||||
return {"message": f"Статус download обновлён для {updated_rows} статей", "updated_rows": updated_rows}
|
||||
except Exception as e:
|
||||
print(f"Ошибка в mark_articles_as_downloaded: {e}")
|
||||
raise
|
||||
|
||||
|
||||
# Глобальное подключение к БД
|
||||
conn = None
|
||||
|
||||
@@ -367,7 +409,6 @@ def create_table_add_sourse():
|
||||
except Exception as e:
|
||||
print(f"Ошибка при создании таблицы sourse: {e}")
|
||||
|
||||
|
||||
def add_sources(url: str, promt: str, status: bool = False):
|
||||
conn = get_connection()
|
||||
try:
|
||||
@@ -384,7 +425,6 @@ def add_sources(url: str, promt: str, status: bool = False):
|
||||
print(f"Ошибка при добавлении источника: {e}")
|
||||
raise
|
||||
|
||||
|
||||
def get_all_sources(category: str):
|
||||
"""Возвращает все записи из таблицы sourse. Сначала показываются записи со status=false"""
|
||||
conn = get_connection()
|
||||
@@ -408,7 +448,6 @@ def get_all_sources(category: str):
|
||||
print(f"Ошибка при получении источников: {e}")
|
||||
return {"error": str(e), "sources": []}
|
||||
|
||||
|
||||
def get_true_sources():
|
||||
"""Возвращает все записи из таблицы sourse. Сначала показываются записи со status=true"""
|
||||
conn = get_connection()
|
||||
@@ -427,7 +466,6 @@ def get_true_sources():
|
||||
print(f"Ошибка при получении источников: {e}")
|
||||
return {"error": str(e), "sources": []}
|
||||
|
||||
|
||||
def update_source_status(url: str, status: bool = True):
|
||||
"""Обновляет статус источника по URL"""
|
||||
conn = get_connection()
|
||||
@@ -443,7 +481,6 @@ def update_source_status(url: str, status: bool = True):
|
||||
print(f"Ошибка при обновлении статуса: {e}")
|
||||
return {"error": str(e), "updated_rows": 0}
|
||||
|
||||
|
||||
def delete_sources(url: str):
|
||||
"""Удаляет источник по URL из таблицы sourse"""
|
||||
conn = get_connection()
|
||||
|
||||
Reference in New Issue
Block a user