187 lines
8.9 KiB
Python
187 lines
8.9 KiB
Python
"""
|
||
Модуль для обработки файлов и управления циклом загрузок
|
||
"""
|
||
import logging
|
||
import time
|
||
from pathlib import Path
|
||
from services.file_finder import FileFinderService
|
||
from services.browser_service import BrowserService
|
||
|
||
|
||
class FileProcessorService:
|
||
"""Сервис для обработки файлов и управления процессом загрузок"""
|
||
|
||
def __init__(self, directory_path, url, download_dir, firefox_path=None):
|
||
"""
|
||
Инициализирует процессор файлов.
|
||
|
||
Args:
|
||
directory_path (str): Путь к директории с .xlsx файлами
|
||
url (str): URL страницы для загрузки файлов
|
||
download_dir (str): Путь для загрузок
|
||
firefox_path (str): Путь к Firefox (опционально)
|
||
"""
|
||
self.directory_path = directory_path
|
||
self.url = url
|
||
self.download_dir = download_dir
|
||
self.firefox_path = firefox_path
|
||
|
||
self.file_finder = FileFinderService()
|
||
self.browser = None
|
||
self.processed_files = 0
|
||
self.failed_files = []
|
||
|
||
logging.info("=" * 70)
|
||
logging.info("🚀 ИНИЦИАЛИЗАЦИЯ ПРОЦЕССОРА ФАЙЛОВ")
|
||
logging.info("=" * 70)
|
||
|
||
def start_processing(self, upload_button_texts=None, process_button_texts=None):
|
||
"""
|
||
Запускает процесс поиска и загрузки файлов.
|
||
|
||
Args:
|
||
upload_button_texts (list): Варианты текста кнопки загрузки файла
|
||
process_button_texts (list): Варианты текста кнопки обработки
|
||
|
||
Returns:
|
||
dict: Результаты обработки
|
||
"""
|
||
if upload_button_texts is None:
|
||
upload_button_texts = ["Загрузить файл", "Выбрать файл", "Добавить файл"]
|
||
|
||
if process_button_texts is None:
|
||
process_button_texts = ["Загрузить", "Обработать", "Преобразовать", "Изменить", "Конвертировать"]
|
||
|
||
results = {
|
||
"total_files": 0,
|
||
"processed_files": 0,
|
||
"failed_files": [],
|
||
"errors": []
|
||
}
|
||
|
||
try:
|
||
# Шаг 1: Поиск файлов
|
||
logging.info("\n📂 ШАГ 1: ПОИСК ФАЙЛОВ")
|
||
logging.info("-" * 70)
|
||
xlsx_files = self.file_finder.find_xlsx_files(self.directory_path, recursive=True)
|
||
results["total_files"] = len(xlsx_files)
|
||
|
||
if not xlsx_files:
|
||
logging.error("❌ Файлы не найдены. Процесс прерван.")
|
||
results["errors"].append("Файлы .xlsx не найдены в указанной директории")
|
||
return results
|
||
|
||
# Шаг 2: Инициализация браузера
|
||
logging.info("\n🌐 ШАГ 2: ИНИЦИАЛИЗАЦИЯ БРАУЗЕРА")
|
||
logging.info("-" * 70)
|
||
self.browser = BrowserService(self.download_dir, self.firefox_path)
|
||
self.browser.open_page(self.url)
|
||
self.browser.wait_page_load(5)
|
||
|
||
# Шаг 3: Обработка каждого файла
|
||
logging.info("\n📋 ШАГ 3: ОБРАБОТКА ФАЙЛОВ")
|
||
logging.info("-" * 70)
|
||
|
||
for idx, file_path in enumerate(xlsx_files, 1):
|
||
# Задержка 5 сек перед следующим файлом (кроме первого)
|
||
if idx > 1:
|
||
logging.info(f"\n⏳ Задержка 5 сек перед следующим файлом...")
|
||
time.sleep(5)
|
||
|
||
logging.info(f"\n📄 Файл {idx}/{len(xlsx_files)}: {file_path.name}")
|
||
logging.info("=" * 70)
|
||
|
||
try:
|
||
# Открываем новую вкладку для каждого файла (кроме первого)
|
||
if idx > 1:
|
||
logging.info(f" Открываю новую вкладку для файла...")
|
||
if not self.browser.open_new_tab(self.url):
|
||
logging.warning(f"⚠️ Не удалось открыть новую вкладку")
|
||
self.browser.wait_page_load(3)
|
||
|
||
# Поиск и клик по кнопке загрузки
|
||
upload_button_found = False
|
||
for btn_text in upload_button_texts:
|
||
if self.browser.click_button_by_text(btn_text):
|
||
upload_button_found = True
|
||
break
|
||
|
||
if not upload_button_found:
|
||
logging.warning(f"⚠️ Не найдена кнопка загрузки файла")
|
||
self.failed_files.append({
|
||
"file": file_path.name,
|
||
"reason": "Кнопка загрузки не найдена"
|
||
})
|
||
results["failed_files"].append(file_path.name)
|
||
continue
|
||
|
||
# Загрузка файла
|
||
self.browser.wait_page_load(1)
|
||
upload_success = self.browser.upload_file(str(file_path))
|
||
|
||
if not upload_success:
|
||
logging.warning(f"⚠️ Ошибка при загрузке файла")
|
||
self.failed_files.append({
|
||
"file": file_path.name,
|
||
"reason": "Ошибка при загрузке файла"
|
||
})
|
||
results["failed_files"].append(file_path.name)
|
||
continue
|
||
|
||
# Поиск и клик по кнопке обработки
|
||
self.browser.wait_page_load(2)
|
||
process_button_found = False
|
||
for btn_text in process_button_texts:
|
||
if self.browser.click_button_by_text(btn_text):
|
||
process_button_found = True
|
||
break
|
||
|
||
if not process_button_found:
|
||
logging.warning(f"⚠️ Не найдена кнопка обработки")
|
||
# Это не критичная ошибка, файл уже загружен
|
||
|
||
# Ожидание обработки
|
||
self.browser.wait_page_load(3)
|
||
self.processed_files += 1
|
||
results["processed_files"] += 1
|
||
logging.info(f"✅ Файл обработан успешно")
|
||
|
||
# Закрываем вкладку после обработки (если это не первый файл)
|
||
if idx > 1:
|
||
logging.info(f" Закрываю вкладку после обработки...")
|
||
self.browser.close_current_tab()
|
||
|
||
except Exception as e:
|
||
logging.error(f"❌ Ошибка при обработке файла: {e}")
|
||
self.failed_files.append({
|
||
"file": file_path.name,
|
||
"reason": str(e)
|
||
})
|
||
results["failed_files"].append(file_path.name)
|
||
|
||
# Итоговый отчет
|
||
logging.info("\n" + "=" * 70)
|
||
logging.info("📊 ИТОГОВЫЙ ОТЧЕТ")
|
||
logging.info("=" * 70)
|
||
logging.info(f"Всего файлов: {results['total_files']}")
|
||
logging.info(f"Обработано успешно: {results['processed_files']}")
|
||
logging.info(f"Ошибок: {len(results['failed_files'])}")
|
||
|
||
if results["failed_files"]:
|
||
logging.warning("\n❌ Файлы с ошибками:")
|
||
for file_info in self.failed_files:
|
||
logging.warning(f" - {file_info['file']}: {file_info['reason']}")
|
||
|
||
logging.info("\n✅ ОБРАБОТКА ЗАВЕРШЕНА")
|
||
logging.info("=" * 70)
|
||
|
||
return results
|
||
|
||
except Exception as e:
|
||
logging.error(f"❌ Критическая ошибка: {e}")
|
||
results["errors"].append(str(e))
|
||
return results
|
||
finally:
|
||
if self.browser:
|
||
self.browser.close()
|