def extract_archives(folder_path): for file i...
Criado em: 8 de maio de 2025
Criado em: 8 de maio de 2025
def extract_archives(folder_path):
for file in os.listdir(folder_path):
full_path = os.path.join(folder_path, file)
if not os.path.isfile(full_path):
continue
textif file.lower().endswith('.zip'): with zipfile.ZipFile(full_path, 'r') as zip_ref: extract_path = os.path.join(folder_path, f"extracted_{os.path.splitext(file)[0]}") os.makedirs(extract_path, exist_ok=True) zip_ref.extractall(extract_path) print(f"📦 Распакован ZIP: {file} → {extract_path}") os.remove(full_path) elif file.lower().endswith('.rar'): with rarfile.RarFile(full_path, 'r') as rar_ref: extract_path = os.path.join(folder_path, f"extracted_{os.path.splitext(file)[0]}") os.makedirs(extract_path, exist_ok=True) rar_ref.extractall(extract_path) print(f"📦 Распакован RAR: {file} → {extract_path}") os.remove(full_path) # Удаляем все пустые папки после распаковки for root, dirs, files in os.walk(folder_path, topdown=False): for dir_name in dirs: dir_path = os.path.join(root, dir_name) try: if not os.listdir(dir_path): os.rmdir(dir_path) print(f"🗑 Удалена пустая папка: {dir_path}") except OSError: pass
def collect_video_files(root_folder):
video_files = []
for dirpath, _, filenames in os.walk(root_folder):
if "FINAL" in dirpath:
continue # ⛔️ Пропускаем папку FINAL
for file in filenames:
if file.lower().endswith(('.mp4', '.mov', '.mkv', '.qt')):
video_files.append(os.path.join(dirpath, file))
return video_files
def process_videos_in_background(folder_path):
try:
extract_archives(folder_path)
text# Удаляем все файлы кроме видео for root, _, files in os.walk(folder_path): for file in files: if not file.lower().endswith(('.mp4', '.mov', '.mkv', '.qt')): file_path = os.path.join(root, file) os.remove(file_path) print(f"🗑 Удален лишний файл: {file_path}") processor_script = r"C:\GENERATOR\PYTHON_FILES\ENVATO_RENDER.py" # Запускаем процесс с unbuffered выводом process = subprocess.Popen( ['python', '-u', processor_script, folder_path], stdout=subprocess.PIPE, stderr=subprocess.STDOUT, universal_newlines=True, encoding='utf-8', errors='replace', creationflags=subprocess.CREATE_NEW_PROCESS_GROUP ) # Мониторим вывод в реальном времени completion_flag = False while True: output_line = process.stdout.readline() if not output_line and process.poll() is not None: break if output_line: print(f"RENDER: {output_line.strip()}") if "🎉 Всё готово! Можно проверять папку FINAL" in output_line: completion_flag = True break # Проверяем статус завершения if completion_flag: print("✅ Рендеринг успешно завершен") else: print("⚠️ Рендеринг завершился без сигнала успеха") except Exception as e: print(f"⚠️ Ошибка в обработке видео: {e}") finally: # Гарантируем завершение процесса if process.poll() is None: process.terminate() process.wait()
def wait_for_downloads_browser_based(driver, batch_name, download_folder, timeout=1800):
print("🧭 Открываем chrome://downloads/ в новой вкладке")
textoriginal_window = driver.current_window_handle driver.execute_script("window.open('');") WebDriverWait(driver, 10).until(lambda d: len(d.window_handles) > 1) new_tab = [handle for handle in driver.window_handles if handle != original_window][0] driver.switch_to.window(new_tab) driver.get("chrome://downloads/") time.sleep(10) print("⏳ Ожидаем завершения загрузок...") def ensure_downloads_tab(): time.sleep(10) if driver.current_window_handle != new_tab: print("🔁 Chrome открыл другую вкладку — возвращаемся на downloads") try: driver.switch_to.window(new_tab) except Exception as e: print(f"⚠️ Не удалось переключиться обратно: {e}") threading.Thread(target=ensure_downloads_tab, daemon=True).start() start_time = time.time() stable_iterations = 0 while time.time() - start_time < timeout: try: items = driver.execute_script(""" const manager = document.querySelector('downloads-manager'); const items = manager.shadowRoot.querySelector('#downloadsList').items; return items ? JSON.stringify(items.map(item => ({ fileName: item.fileName, state: item.state, percent: item.percent }))) : null; """) if not items: print("📭 Список загрузок пуст или не найден.") time.sleep(2) continue downloads = json.loads(items) print(f"\n📦 Найдено {len(downloads)} загрузок:") for d in downloads: state_str = { 0: "⬇️ В процессе", 1: "❌ Отменено", 2: "✅ Завершено", 3: "⚠️ Прервано" }.get(d["state"], f"❓ Неизвестно ({d['state']})") percent = f"{d['percent']}%" if d["state"] == 0 else "—" print(f" ├─ 📄 {d['fileName']} — {state_str} — {percent}") in_progress = [d for d in downloads if d["state"] == 0] if not in_progress: stable_iterations += 1 if stable_iterations >= 3: print("✅ Все загрузки завершены (стабильное состояние)") try: driver.close() driver.switch_to.window(original_window) print("🔙 Вернулись на основную вкладку и закрыли downloads") except Exception as e: print(f"⚠️ Ошибка при закрытии вкладки или переключении: {e}") # 🔽 Начинаем файловое отслеживание и перемещение print("📂 Проверяем загруженные файлы в папке...") time.sleep(3) # дать системе записать файлы existing_files = os.listdir(download_folder) completed_files = [ f for f in existing_files if f.lower().endswith(('.mp4', '.mov', '.mkv', '.zip', '.rar', '.qt')) and not f.endswith('.crdownload') ] if completed_files: batch_folder = os.path.join(download_folder, batch_name) os.makedirs(batch_folder, exist_ok=True) for file_name in completed_files: src = os.path.join(download_folder, file_name) dst = os.path.join(batch_folder, file_name) if os.path.exists(src): shutil.move(src, dst) print(f"📁 Перемещён: {file_name} → {batch_folder}") return True else: print("⚠️ Не удалось найти завершённые файлы после загрузки.") return False else: stable_iterations = 0 except Exception as e: print(f"⚠️ Ошибка при получении данных: {e}") time.sleep(2) else: print("⏱ Время ожидания вышло. Некоторые файлы, возможно, не догрузились.") try: driver.close() driver.switch_to.window(original_window) print("🔙 Вернулись на основную вкладку") except Exception as e: print(f"⚠️ Ошибка при закрытии вкладки или переключении: {e}") return False
def wait_for_downloads(download_folder, batch_name, expected_count=3, max_wait=60, poll_interval=3):
print("⏳ Ожидание загрузки файлов...")
textstart_time = time.time() existing_files = set(os.listdir(download_folder)) tracked_files = set() # 1. Ожидаем появления новых файлов (до expected_count) while time.time() - start_time < max_wait: current_files = set(os.listdir(download_folder)) new_files = current_files - existing_files # Только завершённые файлы (не .crdownload) completed = {f for f in new_files if not f.endswith('.crdownload')} if completed: print(f"📥 Завершенные загрузки: {list(completed)}") tracked_files.update(completed) if len(tracked_files) >= expected_count: break print(f"🔄 Ожидаем ещё... Сейчас завершено: {len(tracked_files)}") time.sleep(poll_interval) if not tracked_files: print("⚠️ Не удалось отследить завершенные загрузки.") return [] print("⌛ Убеждаемся, что файлы не увеличиваются (стабилизировались)...") time.sleep(3) # немного подождать на всякий случай # Перемещение завершённых файлов batch_folder = os.path.join(download_folder, batch_name) os.makedirs(batch_folder, exist_ok=True) for file_name in tracked_files: src = os.path.join(download_folder, file_name) dst = os.path.join(batch_folder, file_name) if os.path.exists(src): shutil.move(src, dst) print(f"📁 Перемещён: {file_name} → {batch_folder}") return list(tracked_files)
def process_bulk_downloads(driver):
"""
Основной цикл: парсит *.txt с линками, разбитыми на секции вида general, waterfall …
─ скачивает файлы пачками по 3‑шт;
─ после каждой успешной загрузки и распаковки перемещает итоговые ВИДЕО‑файлы в
C:\READY<имя‑txt><секция>;
─ в конце каждого .txt запускает рендер всего набора.
Файл .txt «обрезается» по мере обработки, чтобы можно было возобновиться с места сбоя.
"""
global current_account_index
textENVATO_TXT_FOLDER = r"C:\ENVATO" READY_ROOT_FOLDER = r"C:\ENVATO_DOWNLOAD" txt_files = [os.path.join(ENVATO_TXT_FOLDER, f) for f in os.listdir(ENVATO_TXT_FOLDER) if f.lower().endswith(".txt")] # ──────────────────────────────────────────────────────────────────────────── def _update_txt(path, sections_dict): """Перезаписать .txt, оставив только ещё не скачанные ссылки.""" with open(path, "w", encoding="utf-8") as f_out: out_lines = [] for sec, links in sections_dict.items(): if not links: continue out_lines.append(f"*{sec}*") out_lines.extend(links) f_out.write("\n".join(out_lines)) # ──────────────────────────────────────────────────────────────────────────── for txt_path in txt_files: batch_name = os.path.splitext(os.path.basename(txt_path))[0] # ── Читаем и парсим секции sections = {} current = None with open(txt_path, "r", encoding="utf-8") as f_in: for raw in f_in: line = raw.strip() if not line: continue if line.startswith("*") and line.endswith("*") and len(line) > 2: current = line.strip("*").strip() sections[current] = [] elif current: sections[current].append(line) if not sections: print(f"⚠️ В {txt_path} нет секций/ссылок – пропуск.") continue print(f"\n📂 Обработка набора: {batch_name}; ({len(sections)} секций)") # ──────────────────────────────────────────────────────────────────── for section_name, link_pool in sections.items(): if not link_pool: continue ready_folder = os.path.join(READY_ROOT_FOLDER, batch_name, section_name) os.makedirs(ready_folder, exist_ok=True) print(f"\n⭐ Секция *{section_name}* — осталось ссылок: {len(link_pool)}") # ── Цикл пакетных скачиваний внутри секции while link_pool: # ── Проверка лимита try: driver.get("https://www.filesta.com/envato") limit_elem = WebDriverWait(driver, 20).until( EC.presence_of_element_located((By.ID, "remainingLimit"))) remaining = int(limit_elem.text.split("/")[0].strip()) if remaining <= 0: raise Exception("Лимит исчерпан") except Exception as e: print(f"⚠️ {e} – переключаю аккаунт") current_account_index = (current_account_index + 1) % len(ACCOUNTS) driver.quit() driver = login(ACCOUNTS[current_account_index]) continue # пробуем снова batch_links = link_pool[:3] try: # ── Вставляем ссылки в форму «Массовое скачивание» driver.get("https://www.filesta.com/envato") toggle = WebDriverWait(driver, 30).until( EC.element_to_be_clickable( (By.CSS_SELECTOR, "div.card-header[data-target='#bulkDownloadArea']"))) driver.execute_script( "arguments[0].scrollIntoView({behavior:'smooth',block:'center'});", toggle) driver.execute_script("window.scrollBy(0, 200);") toggle.click() textarea = WebDriverWait(driver, 10).until( EC.presence_of_element_located((By.ID, "bulkLinks"))) textarea.clear() textarea.send_keys("\n".join(batch_links)) WebDriverWait(driver, 10).until( EC.element_to_be_clickable((By.ID, "startBulkDownload"))).click() print(f"⬇️ Скачивание {len(batch_links)} файл(ов)…") # ── Ждём завершения через chrome://downloads ok = wait_for_downloads_browser_based( driver, batch_name=f"{batch_name}_{section_name}", download_folder=ready_folder ) if not ok: raise Exception("Скачивание не подтвердило успех") # Распаковка, удаление мусора extract_archives(ready_folder) for root, _, files in os.walk(ready_folder): for f in files: if not f.lower().endswith(('.mp4', '.mov', '.mkv', '.qt')): os.remove(os.path.join(root, f)) print("✅ Пакет успешно обработан") # ── Удаляем обработанные ссылки из пула и обновляем .txt link_pool = link_pool[3:] sections[section_name] = link_pool _update_txt(txt_path, sections) except Exception as ex: print(f"⚠️ Ошибка внутри пакета: {ex}\n🔄 Повтор через 3 сек") time.sleep(3) continue # повторим пакет # ─────────────────────────────────────────────── # Когда ВСЕ секции .txt скачаны → рендер if all(not lst for lst in sections.values()): parent_ready = os.path.join(READY_ROOT_FOLDER, batch_name) print(f"\n🚀 Все секции {batch_name} готовы — запускаю рендер.") process_videos_in_background(parent_ready) else: print(f"⚠️ В {batch_name} остались необработанные ссылки – рендер пропущен") print("\n🔥 Все .txt обработаны!")
def login(account):
global current_account_index
extension_path = r"C:\GENERATOR\PYTHON_FILES\zencap"
download_folder = r"C:\ENVATO_DOWNLOAD"
proxy = "127.0.0.1:1081"
textchrome_options = Options() chrome_options.add_argument(f"--load-extension={extension_path}") chrome_options.add_experimental_option("prefs", { "download.default_directory": download_folder, "download.prompt_for_download": False, "download.directory_upgrade": True, "safebrowsing.enabled": True, "profile.content_settings.exceptions.automatic_downloads.*.setting": 1, "profile.default_content_setting_values.automatic_downloads": 1, "credentials_enable_service": False, "profile.password_manager_enabled": False, "profile.default_content_settings.popups": 0 }) service = Service() driver = webdriver.Chrome(service=service, options=chrome_options) driver.set_page_load_timeout(10) # Максимальное время загрузки страницы — 10 секунд try: try: driver.get("https://www.filesta.com/login") except TimeoutException as e: print(f"Страница не загрузилась за 10 секунд") driver.execute_script("window.stop();") # <<< Останавливает загрузку вкладки pass WebDriverWait(driver, 30).until( EC.presence_of_element_located((By.CSS_SELECTOR, "iframe[title='reCAPTCHA']")) ) print("Ожидание прохождения капчи...") WebDriverWait(driver, 300).until( lambda d: d.execute_script("return document.getElementById('g-recaptcha-response').value") != "" ) print("Капча пройдена!") driver.find_element(By.NAME, "InputEmail").send_keys(account['email']) time.sleep(0.5) driver.find_element(By.NAME, "InputPassword").send_keys(account['password']) time.sleep(0.5) driver.find_element(By.CSS_SELECTOR, "button.btn.btn-primary.btn-user.btn-block").click() WebDriverWait(driver, 10).until(EC.url_changes("https://www.filesta.com/login")) print("Вход выполнен!") time.sleep(3) return driver except Exception as e: print(f"❌ Ошибка при логине: {e}") driver.quit() current_account_index = (current_account_index + 1) % len(ACCOUNTS) raise
def main_loop():
global current_account_index
while True:
try:
print(f"\n🔁 Используем аккаунт: {ACCOUNTS[current_account_index]['email']}")
driver = login(ACCOUNTS[current_account_index])
process_bulk_downloads(driver)
print("✅ Загрузка завершена")
break
except Exception as e:
print(f"⚠️ Ошибка: {e}\n⏳ Перезапуск через 5 секунд...")
current_account_index = (current_account_index + 1) % len(ACCOUNTS)
time.sleep(5)
continue # Перезапуск
textfinally: try: driver.quit() print("🧹 Браузер закрыт") except: pass
if name == "main":
main_loop()
⭐ Секция evora — осталось ссылок: 10
⚠️ Message: timeout: Timed out receiving message from renderer: 8.757
(Session info: chrome=135.0.7049.116)
Stacktrace:
GetHandleVerifier [0x00007FF7D9B7EFA5+77893]
GetHandleVerifier [0x00007FF7D9B7F000+77984]
(No symbol) [0x00007FF7D99491BA]
(No symbol) [0x00007FF7D99365CC]
(No symbol) [0x00007FF7D99362BA]
(No symbol) [0x00007FF7D9933F67]
(No symbol) [0x00007FF7D993491F]
(No symbol) [0x00007FF7D99434FE]
(No symbol) [0x00007FF7D9959931]
(No symbol) [0x00007FF7D99608DA]
(No symbol) [0x00007FF7D993508D]
(No symbol) [0x00007FF7D9959665]
(No symbol) [0x00007FF7D99EF415]
(No symbol) [0x00007FF7D99C6F03]
(No symbol) [0x00007FF7D9990328]
(No symbol) [0x00007FF7D9991093]
GetHandleVerifier [0x00007FF7D9E37B6D+2931725]
GetHandleVerifier [0x00007FF7D9E32132+2908626]
GetHandleVerifier [0x00007FF7D9E500F3+3031443]
GetHandleVerifier [0x00007FF7D9B991EA+184970]
GetHandleVerifier [0x00007FF7D9BA086F+215311]
GetHandleVerifier [0x00007FF7D9B86EC4+110436]
GetHandleVerifier [0x00007FF7D9B87072+110866]
GetHandleVerifier [0x00007FF7D9B6D479+5401]
BaseThreadInitThunk [0x00007FFA6026259D+29]
RtlUserThreadStart [0x00007FFA6216AF38+40]
– переключаю аккаунт
ПОЧЕМУ ЭТОТ КОД ПРИ TIMEOUT ЗАГРУЗКИ СТРАНИЦЫ - ЗАКРЫВАЕТ БРАУЗЕР И ПЕРЕКЛЮЧАЕТ АККАУНТ? КАК МНЕ СДЕЛАТЬ ЧТОБЫ ТАЙМАУТ БРАУЗЕРА НЕ ВЫЗЫВАЛ СМЕНУ АККАУНТА И НЕ ЗАКРЫВАЛ БРАУЗЕР? МНЕ НУЖНО ЧТОБЫ ПРОСТО ЗАГРУЗКА СТРАНИЦЫ ОСТАНАВЛИВАЛАСЬ И КОД ШЕЛ ДАЛЬШЕ.
Причина, по которой при таймауте сразу закрывается браузер и идёт переключение аккаунта, проста:
таймаут → исключение TimeoutException
(или близкий ему WebDriverException: Timed out receiving message from renderer
) «прорывается» наружу, попадает в общий except Exception
— а там везде логика одинаковая: driver.quit()
+ смена аккаунта. Нужно перехватывать именно таймауты там, где они возникают, и считать их «мягкой» ошибкой, а не критической.
get
pythonfrom selenium.common.exceptions import TimeoutException, WebDriverException def safe_get(driver, url, timeout=10): """Открыть url, но если страница грузится дольше timeout, останавливаем загрузку и работаем дальше с текущим драйвером.""" try: driver.set_page_load_timeout(timeout) driver.get(url) except (TimeoutException, WebDriverException): print(f"⚠️ Timeout при загрузке {url} — стопим вкладку и продолжаем") try: driver.execute_script("window.stop();") # стопим загрузку except Exception: pass
Дальше вместо driver.get(...)
зовём safe_get(driver, ...)
во всех местах, где таймаут безобиден (проверка лимита, переход на downloads и т. д.).
process_bulk_downloads
pythonwhile True: try: # ⭐️ здесь критична только потеря сессии или ошибка парсинга, # а таймаут загрузки страницы – нет safe_get(driver, "https://www.filesta.com/envato") # ← заменили limit_elem = WebDriverWait(driver, 20).until( EC.presence_of_element_located((By.ID, "remainingLimit")) ) remaining = int(limit_elem.text.split("/")[0].strip()) if remaining <= 0: raise RuntimeError("Лимит исчерпан") # критическая except TimeoutException: print("🔄 Страница не успела прогрузиться, пробуем ещё раз") continue # та же учётка, тот же драйвер except Exception as e: print(f"⚠️ {e} – переключаю аккаунт") driver.quit() current_account_index = (current_account_index + 1) % len(ACCOUNTS) driver = login(ACCOUNTS[current_account_index]) continue
login
except TimeoutException
— он останавливает загрузку.TimeoutException
, но уже в WebDriverWait
. Поэтому добавляем отдельную ветку:pythontry: # … (safe_get не нужен – уже вложенный catch) WebDriverWait(driver, 30).until( EC.presence_of_element_located((By.CSS_SELECTOR, "iframe[title='reCAPTCHA']")) ) except TimeoutException: print("⚠️ Не нашли reCAPTCHA, страница могла не догрузиться — обновляем и ждём ещё") driver.refresh() continue # повторяем попытку без выхода из аккаунта
А общий except Exception
оставляем как «жёсткий» – он приведёт к закрытию драйвера и переключению аккаунта только если случилось что‑то действительно серьёзное (неверный пароль, капча не решена, 500 и т.д.).
pageLoadStrategy
Если хотите вообще убрать ожидание полной загрузки (тем более вы всё равно ждёте элементы через WebDriverWait
), добавьте в Options
:
pythonchrome_options.set_capability("pageLoadStrategy", "none")
Тогда Selenium вернётся сразу после получения первого байта, и safe_get
понадобится только как «страховка» от подвисаний рендерера.
TimeoutException
, WebDriverException
, добавьте safe_get
.driver.get(...)
на safe_get(...)
.get
идёт WebDriverWait
, отловите TimeoutException
до общего except Exception
.except TimeoutException:
от «catch‑all».После этих правок «Timed out receiving message from renderer» лишь остановит загрузку страницы, цикл продолжит работу с тем же браузером и тем же аккаунтом, а переключение произойдёт только при действительно фатальной ошибке.