Yandex Disk Protected Folder Downloader
Скрипт для рекурсивного скачивания большой публичной папки Яндекс Диска, защищённой паролем.
Он получает список объектов через веб-API Яндекс Диска, сохраняет структуру каталогов и скачивает каждый файл отдельно через wget.
Возможности
- чтение всех пользовательских настроек из файла
.envрядом со скриптом; - использование готового cookie
passTokenлибо автоматическое получение токена по паролю через Chromium и Playwright; - постоянный профиль Chromium с повторным использованием cookies;
- рекурсивный обход вложенных каталогов;
- двухэтапная работа: сначала полный список, затем скачивание;
- сохранение полного списка в
yandex-download-manifest.jsonl; - исключение служебного элемента текущего каталога из расчёта
offset; - сохранение исходной структуры каталогов;
- продолжение прерванной загрузки через
wget --continue; - автоматический пропуск файлов, размер которых уже совпадает с серверным;
- проверка итогового размера каждого скачанного файла;
- паузы между запросами прямых ссылок и периодические длительные паузы;
- повторные HTTP-запросы при временных ошибках
429,500,502,503и504;
Как работает двухэтапная загрузка
Этап 1 — получение полного списка
Скрипт быстро обходит страницы каталога:
0 → 40 → 80 → 120 → ... → completed=True
На этом этапе:
download-urlне запрашивается;wgetне запускается;- файлы не скачиваются;
- для каждого файла сохраняются серверные метаданные и относительный каталог;
- вложенные каталоги также обходятся полностью;
- служебное описание текущей папки не учитывается при увеличении
offset.
После успешного завершения обхода создаётся:
OUTPUT_DIR/yandex-download-manifest.jsonl
Manifest записывается атомарно: сначала создаётся временный файл .tmp, после чего он заменяет предыдущий manifest.
Пример одной строки:
{"relative_directory":".","item":{"name":"FL_9J1915234BP_1654_40013103010803_V001_S.frf","type":"file","size":793122,"path":"public_hash:/ODIS/Flashdaten/Brand-A/FL_9J1915234BP_1654_40013103010803_V001_S.frf"}}
Этап 2 — скачивание файлов
После получения completed=True скрипт начинает скачивание по полностью собранному плану:
- проверяет наличие локального файла;
- сравнивает его размер с серверным;
- пропускает полностью скачанный файл;
- для отсутствующего или неполного файла получает временный
download-url; - запускает
wget --continue; - проверяет размер после завершения.
Текущая версия сохраняет manifest для контроля и последующего анализа, но при новом запуске всё равно заново выполняет этап 1 и получает актуальный список с Яндекса.
Требования
Поддерживается Linux с Python 3.
Необходимые пакеты:
sudo apt install -y python3 python3-requests wget
Playwright и Chromium для автоматического получения passToken:
python3 -m pip install --user playwright
python3 -m playwright install chromium
Настройка
Все основные параметры находятся в файле sample.env
TARGET_URL
Полная публичная ссылка на нужный каталог:
TARGET_URL="https://disk.yandex.ru/d/cWn4RgSdFcSZXw/ODIS/Flashdaten/Brand-A"
Для вложенного каталога необходимо указывать полный путь после идентификатора публичной ссылки.
PUBLIC_LINK_PASSWORD
Пароль публичной ссылки:
PUBLIC_LINK_PASSWORD="реальный пароль публичной ссылки"
Если оставить значение пустым, программа попытается использовать cookies из постоянного профиля Chromium. Если действующего passToken нет и запуск производится из терминала, пароль будет запрошен без отображения введённых символов.
OUTPUT_DIR
Каталог, куда будут сохранены файлы:
OUTPUT_DIR = "/mnt/hdd1-4TB/ODIS/Flashdaten/Brand-V"
Каталог будет создан автоматически, если у пользователя есть права на его создание. Внутри него также могут появиться:
yandex-download-manifest.jsonl
yandex-captcha-url.txt
Настройки Playwright
PLAYWRIGHT_PROFILE_DIR="./playwright-profile"
PLAYWRIGHT_HEADLESS="false"
PLAYWRIGHT_TIMEOUT="120"
PLAYWRIGHT_PROFILE_DIR— постоянный профиль Chromium;PLAYWRIGHT_HEADLESS=false— показывает окно браузера и позволяет вручную пройти CAPTCHA;PLAYWRIGHT_HEADLESS=true— запускает Chromium без окна; при CAPTCHA программа остановится;PLAYWRIGHT_TIMEOUT— максимальное время ожидания полученияpassToken, в секундах.
Относительный путь профиля вычисляется относительно каталога, где находится .env и скрипт.
Задержки между страницами
PAGE_DELAY_MIN="0.5"
PAGE_DELAY_MAX="1.5"
Эти задержки используются только на этапе 1 между запросами fetch-list.
После перехода на двухэтапную схему страницы перечисляются подряд и больше не разделяются длительным скачиванием файлов. Поэтому состояние пагинации живёт значительно меньше времени.
Задержки между файлами
FILE_DELAY_MIN="1.5"
FILE_DELAY_MAX="3.5"
Случайная пауза перед каждым запросом download-url на этапе 2.
Длительные паузы
COOLDOWN_EVERY_FILES="100"
COOLDOWN_MIN="60"
COOLDOWN_MAX="120"
После каждых 100 запросов download-url программа дополнительно ждёт от 60 до 120 секунд.
Чтобы отключить длительные паузы:
COOLDOWN_EVERY_FILES="0"
COOLDOWN_MIN="0"
COOLDOWN_MAX="0"
HTTP-таймауты и повторы
CONNECT_TIMEOUT="30"
READ_TIMEOUT="120"
HTTP_RETRIES="5"
CONNECT_TIMEOUT— таймаут установки соединения;READ_TIMEOUT— таймаут чтения ответа API;HTTP_RETRIES— число автоматических повторов временных ошибок.
Пример вывода
Получение токена
[AUTH] Открываю защищённую ссылку в Chromium...
[AUTH] Используется passToken из сохранённого профиля.
Либо:
[AUTH] Поле пароля найдено (input[type="password"]).
[AUTH] Ввожу пароль публичной ссылки...
[AUTH] Пароль введён; отправляю форму...
[AUTH] passToken получен.
Этап 1
[INFO] Открываю исходную ссылку...
[INFO] Папка открыта.
[INFO] Корневой hash: public_hash:/ODIS/Flashdaten/Brand-A
[INFO] Этап 1/2: получаю полный список файлов...
[DIR ] /mnt/hdd1-4TB/ODIS/Flashdaten/Brand-A
[PAGE] получено API=41, дочерних=40, служебных=1, offset=0->40, completed=False
[WAIT] 0.8 с перед следующей страницей
[PAGE] получено API=10, дочерних=9, служебных=1, offset=12080->12089, completed=True
[INFO] Полный список получен: 12089 файлов.
[INFO] Manifest сохранён: /mnt/hdd1-4TB/ODIS/Flashdaten/Brand-A/yandex-download-manifest.jsonl
Этап 2
[INFO] Этап 2/2: начинаю скачивание по сохранённому списку...
[SKIP] /mnt/hdd1-4TB/ODIS/Flashdaten/Brand-A/FL_0DL300014F_3123_idMA_sw.frf (2.14 MiB)
[GET ] /mnt/hdd1-4TB/ODIS/Flashdaten/Brand-A/FL_9J1915234BP_1654_40013103010803_V001_S.frf (774.53 KiB)
[WAIT] 2.6 с перед запросом ссылки
2026-08-03 URL:https://s684vla.storage.yandex.net/rdisk/... [793122/793122]
Итоговая статистика
================ РЕЗУЛЬТАТ ================
Найдено файлов: 12089
Скачано сейчас: 529
Уже было скачано: 11560
Ошибок: 0
Известный общий объём: 49.04 GiB
===========================================
CAPTCHA
При большом количестве запросов Яндекс может вернуть CAPTCHA.
Скрипт распознаёт ответ:
{
"type": "captcha"
}
После этого загрузка немедленно прекращается.
Будет выведена ссылка:
ЯНДЕКС ПОТРЕБОВАЛ CAPTCHA
Открой ссылку ниже в обычном браузере с того же внешнего IP:
https://disk.yandex.ru/showcaptcha?...
Ссылка также сохраняется в файл:
/mnt/hdd1-4TB/ODIS/Flashdaten/Brand-V/yandex-captcha-url.txt
Ошибка 409 Conflict
Внутренний API /public/api/fetch-list может вернуть 409 Conflict, если серверное состояние пагинации изменилось или стало недействительным.
Двухэтапная схема значительно снижает вероятность такой ошибки, потому что все страницы каталога запрашиваются до начала скачивания файлов.
409 не следует считать признаком конца каталога. Если он всё же возник на этапе 1:
- не удаляйте уже скачанные файлы;
- повторно запустите программу;
- скрипт получит новый
skи начнёт перечисление заново; - на этапе 2 существующие файлы будут пропущены.
Полным считается только обход, завершившийся серверным признаком:
completed=True
Коды завершения
Скрипт использует следующие коды выхода:
| Код | Значение |
|---|---|
0 |
загрузка завершена без ошибок |
1 |
загрузка завершена с ошибками |
2 |
ошибка конфигурации или отсутствует wget |
75 |
Яндекс потребовал CAPTCHA |
130 |
процесс остановлен через Ctrl+C |
Проверить код после завершения:
echo $?