- Автор темы
-
- #1
Рассматривая текущие реалии можно предположить, что вполне возможно, в довольно скором времени начнется миграция видеоблогеров на другие платформы для размещения своего видеоконтента. И вполне возможно, что одной из таких платформ станет Rutube. Тем более не так давно они провели презентацию, из которой стало уже понятно, что движения по платформе, хоть какие-то появились. Ну и если они еще предложат «вкусные» условия по монетизации контента, то, почему бы и нет? Но, все это лирика. И по большей части относится к разряду предсказаний или гадания на кофейной гуще. У меня же здесь немного другая цель. Я решил попробовать скачать видео с данной платформы. И ниже показываю, что у меня получилось.
Что понадобиться?
Для начала нужно установить библиотеку requests. Здесь все достаточно просто. Пишем в терминале редактора кода или в терминале ОС, которую вы используете, команду:
pip install requests
После того, как данная библиотека установиться, нужно будет скачать ffmpeg и прописать к нему путь в переменной среды path. Собственно скачиваем саму программу. Никакой установки она не требует. Достаточно скопировать ее в то место, где она будет жить в последующем и скопировать к ней путь. Далее идем в «Пуск», «Параметры», «Система», «О программе» и в панели справа выбираем пункт меню «Дополнительные параметры системы».
Параметры
В открывшемся окне щелкаем по кнопке «Переменные среды».
Свойства системы
На следующем шаге выделяем переменную Path и щелкаем по кнопке «Изменить».
Переменные среды
Нажимаем кнопку «Создать» и вписываем путь к исполняемому файлу. К примеру: «C:\FFMPEG\ffmpeg.exe». Путь вписывается без кавычек. После чего жмем кнопку «ОК» и закрываем все открытые ранее окна.
Изменить переменную среды
На этом подготовительный этап можно считать завершенным. Приступим к исследованию сайта и написанию кода.
Исследуем код страницы с видео
Для примера я взял короткое видео по адресу:
Ссылка скрыта от гостей
Часть этого адреса, а именно идентификатор видео нам понадобиться в дальнейшем. Почему видео небольшое? Ну, тут все просто. Это снизит нагрузку на сервер Rutube с моего адреса. Так как скачивать во время тестов придется меньше. И меньше вероятность того, что сервер меня заблокирует. И чтобы банально долго не ждать скачивания. Ведь при написании кода нужно будет проводить тест работы кода.
Данная платформа пилит видео на сегменты. Примерно по восемь секунд в каждом, а потом, в процессе воспроизведения видео их подгружает. Это не особенно хорошо. Но, думаю, что не критично. Исследуем код страницы. Щелкаем правой кнопкой мыши по странице с видео и выбираем в меню пункт «Исследовать элемент».
Исследовать элемент
Скажу сразу, что в коде страницы ничего интересного нет. Ну или того, что привело бы нас к ссылке на сегменты видео. Поэтому даже не буду в нем копаться. Перехожу на вкладку Network, выставляю фильтр для запросов Feth/XHR и обновляю страницу с видео. После обновления страницы в консоль посыпалось большое количество запросов. Я, конечно же, предварительно покопался в них и уже знаю, что нам нужен запрос имя которого начинается с ?no_404… Это GET запрос который возвращает JSON с параметрами видео. Вот собственно он на картинке:
Запрос с JSON
Жмем мышкой на запрос и видим в правой колонке консоли, что в JSON, который прилетает в ответ на запрос можно получить самую разнообразную информацию о видео. Но, в данный момент, так как мы хотим его скачать, нас интересуют такие параметры как информация о названии канала, информация о названии видео. При желании, тут же доступна информация и о категории, к которой данное видео относиться, но здесь нас интересует только название канала. Находиться оно по пути [“author”][“name”].
Название канала и категория
Прокручиваем запрос немного ниже и видим, что информация о названии видео так же присутствует и находиться в разделе [“title”]. И основное, то, что интересует больше всего, это ссылка на список плейлистов с различным разр
ешением видео. Это не сам плейлист, а только список со ссылками. Тем не менее, его нужно получить для того, чтобы можно было двигаться дальше.
Название видео и путь к списку плейлистов
Получаем данные из JSON
Таким образом, из данного JSON мы можем получить информацию о названии канала, информацию о названии видео и ссылку на список плейлистов. Как я писал выше, ссылка на видео в данном случае нам пригодиться, так как содержит его идентификатор. Это будет нужно для того, чтобы в будущем мы могли загрузить любое видео с видеохостинга, а не только видео из теста. Копируем ссылку на GET-запрос. Щелкаем правой кнопкой по нужному нам запросу и выбираем пункт меню «Copy – Copy link address». Вот собственно ссылка, которую я скопировал:
Ссылка скрыта от гостей
Часть ссылки после options как раз и есть идентификатор видео, который мы будем менять в будущем для загрузки других видео. Ну, а теперь, когда мы знаем, откуда брать данные, напишем код для их получения. На всякий случай мне понадобятся заголовки для запроса. Их я скопирую из самого запроса на вкладке Headers. Для заголовков я возьму user-agent и accept.
Python:
headers = {
'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) '
'Chrome/98.0.4758.132 YaBrowser/22.3.1.892 Yowser/2.5 Safari/537.36',
'accept': '*/*'
}
Напишем функцию, которая будет получать JSON и извлекать из него данные: get_m3u8_list(url):
Python:
def get_m3u8_list(url):
req = requests.get(url=url, headers=headers)
video_data = req.json()
video_author = video_data['author']['name']
video_title = video_data['title']
dict_repl = ["/", "\\", "[", "]", "?", "'", '"', ":", "."]
for repl in dict_repl:
if repl in video_title:
video_title = video_title.replace(repl, "")
if repl in video_author:
video_author = video_author.replace(repl, "")
video_title = video_title.replace(" ", "_")
video_author = video_author.replace(" ", "_")
video_m3u8 = video_data['video_balancer']['m3u8']
return video_author, video_title, video_m3u8
Так как в названии канала и в названии видео могут содержаться всяческие символы, которые будут мешать при сохранении видео с нужным названием, а так же создания папки с названием канала, создадим список из наиболее часто встречающихся символов и пробежимся по названию канала и видео в цикле, где эти символы и заменим с помощью replace(). А после пробелы в названии канала и видео заменим на знак «_». Это будет нужно для того, чтобы ffmpeg при конвертации отработал корректно. Иначе он выдает ошибку о том, что видео для конвертации не найдено. Можно эту ошибку обойти. Но, чтобы не усложнять код, проще заменить пробелы. Ну и далее получаем ссылку на список плейлистов. После чего возвращаем из функции полученные значения. Вот код данного этапа:
Получение данных из JSON
Так как мы получаем список со ссылками на плейлисты, то нужно его исследовать. А вернее, то, что мы получаем. А получаем мы содержимое со ссылками, где последняя ссылка, это ссылка на видео самого высокого качества. Ее мы и будем брать для загрузки сегментов. Таким образом у нас отпадет необходимость в поиске видео самого высокого качества и в случае, если, к примеру, видео с разрешением 720p не окажется в списке, мы получим ссылку на самое максимально возможное качество для данного видео.
Список со ссылками на плейлисты
Получаем ссылку на плейлист
Итак, мы получили список с нужными нам данными. Теперь нужно получить список плейлистов и извлечь из него ссылку на нужный нам. В плейлисте содержится список видеосегментов, которые подгружаются при просмотре видео. И данный список нам будет очень нужен. Позже поймете зачем.
Создадим функцию get_link_from_m3u8(url_m3u8), которая получает на входе ссылку на список ссылок на плейлисты. А на выходе этой функции мы получим ссылку на нужный нам плейлист. Ниже приведен уже модифицированный код с добавленной в него функцией:
Получение ссылки на нужный плейлист
Ну, а теперь небольшие пояснения. Сохраняем полученные значения в текстовый файл, после, открываем его и загоняем построчно в список. Ну, а затем уже извлекаем из списка последний элемент. Возвращаем полученное значение для дальнейшего использования.
Получаем количество сегментов видео
Что же, теперь у нас есть ссылка на плейлист, в котором содержаться все имена сегментов, которые подгружаются в процессе воспроизведения. Нам нужно получить имя самого последнего сегмента и вычленить из него порядковый номер, для того, чтобы понимать, сколько сегментов для загрузки нужно будет всего. Создаем функцию get_segment_count(m3u8_link). На входе она получает ссылку на плейлист, а на выходе возвращает количество сегментов. Вот код с добавленной функцией:
Получение количества сегментов видео
Ну, а теперь пояснения. Тут все достаточно просто. Делаем запрос и получаем плейлист. Создаем словарь для того, чтобы в него добавлять полученные значения с именами видеосегментов. Заполняем в цикле список из запроса. После чего получаем -2 элемент. В -1 элементе содержится служебная информация. Далее разбиваем полученную строку и очищаем от ненужных нам символов. Ну, а далее получаем цифру из названия последнего сегмента. Это и будет искомое значение. Его мы и возвращаем из функции.
Получаем ссылку для загрузки видео
Теперь нужно получить ссылку для загрузки видео, в которую мы будем подставлять нужные значения и скачивать сегменты. Данная ссылка у нас уже есть. Она содержится в ссылке на плейлист. Нужно ее только очистить от всего лишнего. Поэтому создадим функцию, в которой это и сделаем. Назовем ее, к примеру, get_download_link(m3u8_link). На входе в нее будет передаваться ссылка на плейлист, очищаться и на выходе возвращаться уже очищенной. Вот код с данной функцией:
Получаем ссылку для загрузки видео
Загружаем сегменты видео
Теперь, когда у нас есть вся нужная информация, можно приступать к загрузке сегментов. Для этого я создам функцию get_download_segment(link, count), в которую на входе будет подаваться очищенная в предыдущей функции ссылка, и количество сегментов для загрузки. Возвращать данная функция ничего не будет. Она будет просто загружать сегменты видео. И код еще раз, уже с функцией загрузки сегментов:
Загрузка сегментов видео
Для того, чтобы не мусорить сегментами в той папке, где работает наш скрипт, создадим временную папку для загрузки в нее сегментов. Проверяем ее наличие, а если нет – создаем. Далее создаем цикл, который пробегается по диапазону с количеством сегментов. В этом цикле мы формируем нужную нам ссылку и загружаем сегмент на диск, в только что созданную папку. Чтобы не было скучно во время этого процесса, выведем принты в терминал о загрузке каждого сегмента и об полном ее окончании, когда уже все сегменты будут загружены.
Объединяем сегменты в одно видео формата ts и конвертируем в mp4
Чисто практически, да и в теории, можно оставить объединенное видео в формате ts. Оно вполне себе проигрывается с помощью проигрывателя. Но, мне не понравился небольшой глюк при проигрывании. Если я хочу видео перемотать, у него начинается рассинхронизация между звуком и видео. Можно подобрать, конечно, плеер, который будет это все корректно воспроизводить. Но проще видео конвертировать в нужный формат, а именно mp4. Создаем функцию merge_ts(author, title, count), на вход которой подаем название канала, название видео и количество сегментов загруженного видео для объединения. Далее уже будет представлен полный код загрузки и конвертации видео, а пояснения по последней функции я дам немного ниже:
Полный код для загрузки видео
А теперь пояснения. Открываем файл для записи в побайтовом режиме. После чего создаем цикл, в котором по очереди открываем и читаем все загруженные сегменты побайтово для добавления их с помощью shutil.copyfileobj в один файл для последующей записи. Ну и сохраняем файл в папке с сегментами, но с именем, которое уже было получено из JSON файла в самом начале.
Ну, а далее создаем папку с названием канала и запускаем конвертацию видео с помощью os.system, которая позволяет выполнять консольные команды. Нужно сказать, что я использую в данный момент Windows. В ОС Linux нужно будет воспользоваться функцией subprocess.
Теперь, после того, как файл конвертирован и сохранен, остается только прибраться в директории. Для этого сканируем папку с сегментами. Получаем список файлов и в цикле их все удаляем. После чего удаляем и саму папку.
В принципе все. Способ достаточно простой. Я думал, что будет сложнее. Кто знает, может быть с течением времени они что-то поменяют в коде и написанный мной скрипт перестанет работать. Но в данное время, все работает. Конечно же, те кто уже давно программирует на питоне, могут значительно улучшить данный код. Но, снова прошу вас меня сильно не пинать. Я только учусь программировать. А для новичков, вроде меня, для понимания общих принципов работы, данный код, думаю, будет полезен.
Сюда же, для большей универсальности кода, чтобы он мог работать под разными ОС, можно добавить определение платформы, на которой он запущен и в зависимости от этого менять разделители в путях к папкам и файлам. Так же, в зависимости от ОС вызывать терминал разными способами...
Спасибо за внимание! Надеюсь, что эта статься кому-то смогла помочь )
Что понадобиться?
Для начала нужно установить библиотеку requests. Здесь все достаточно просто. Пишем в терминале редактора кода или в терминале ОС, которую вы используете, команду:
pip install requests
После того, как данная библиотека установиться, нужно будет скачать ffmpeg и прописать к нему путь в переменной среды path. Собственно скачиваем саму программу. Никакой установки она не требует. Достаточно скопировать ее в то место, где она будет жить в последующем и скопировать к ней путь. Далее идем в «Пуск», «Параметры», «Система», «О программе» и в панели справа выбираем пункт меню «Дополнительные параметры системы».
Параметры
В открывшемся окне щелкаем по кнопке «Переменные среды».
Свойства системы
На следующем шаге выделяем переменную Path и щелкаем по кнопке «Изменить».
Переменные среды
Нажимаем кнопку «Создать» и вписываем путь к исполняемому файлу. К примеру: «C:\FFMPEG\ffmpeg.exe». Путь вписывается без кавычек. После чего жмем кнопку «ОК» и закрываем все открытые ранее окна.
Изменить переменную среды
На этом подготовительный этап можно считать завершенным. Приступим к исследованию сайта и написанию кода.
Здесь хотелось бы вставить небольшой дисклеймер. Я только начинаю программировать на питоне, потому прошу меня сильно не пинать. Что получилось, то получилось. Но, оно работает. Хотя, нет пределу для совершенства… )
Исследуем код страницы с видео
Для примера я взял короткое видео по адресу:
Ссылка скрыта от гостей
Часть этого адреса, а именно идентификатор видео нам понадобиться в дальнейшем. Почему видео небольшое? Ну, тут все просто. Это снизит нагрузку на сервер Rutube с моего адреса. Так как скачивать во время тестов придется меньше. И меньше вероятность того, что сервер меня заблокирует. И чтобы банально долго не ждать скачивания. Ведь при написании кода нужно будет проводить тест работы кода.
Данная платформа пилит видео на сегменты. Примерно по восемь секунд в каждом, а потом, в процессе воспроизведения видео их подгружает. Это не особенно хорошо. Но, думаю, что не критично. Исследуем код страницы. Щелкаем правой кнопкой мыши по странице с видео и выбираем в меню пункт «Исследовать элемент».
Исследовать элемент
Скажу сразу, что в коде страницы ничего интересного нет. Ну или того, что привело бы нас к ссылке на сегменты видео. Поэтому даже не буду в нем копаться. Перехожу на вкладку Network, выставляю фильтр для запросов Feth/XHR и обновляю страницу с видео. После обновления страницы в консоль посыпалось большое количество запросов. Я, конечно же, предварительно покопался в них и уже знаю, что нам нужен запрос имя которого начинается с ?no_404… Это GET запрос который возвращает JSON с параметрами видео. Вот собственно он на картинке:
Запрос с JSON
Жмем мышкой на запрос и видим в правой колонке консоли, что в JSON, который прилетает в ответ на запрос можно получить самую разнообразную информацию о видео. Но, в данный момент, так как мы хотим его скачать, нас интересуют такие параметры как информация о названии канала, информация о названии видео. При желании, тут же доступна информация и о категории, к которой данное видео относиться, но здесь нас интересует только название канала. Находиться оно по пути [“author”][“name”].
Название канала и категория
Прокручиваем запрос немного ниже и видим, что информация о названии видео так же присутствует и находиться в разделе [“title”]. И основное, то, что интересует больше всего, это ссылка на список плейлистов с различным разр
ешением видео. Это не сам плейлист, а только список со ссылками. Тем не менее, его нужно получить для того, чтобы можно было двигаться дальше.
Название видео и путь к списку плейлистов
Получаем данные из JSON
Таким образом, из данного JSON мы можем получить информацию о названии канала, информацию о названии видео и ссылку на список плейлистов. Как я писал выше, ссылка на видео в данном случае нам пригодиться, так как содержит его идентификатор. Это будет нужно для того, чтобы в будущем мы могли загрузить любое видео с видеохостинга, а не только видео из теста. Копируем ссылку на GET-запрос. Щелкаем правой кнопкой по нужному нам запросу и выбираем пункт меню «Copy – Copy link address». Вот собственно ссылка, которую я скопировал:
Ссылка скрыта от гостей
Часть ссылки после options как раз и есть идентификатор видео, который мы будем менять в будущем для загрузки других видео. Ну, а теперь, когда мы знаем, откуда брать данные, напишем код для их получения. На всякий случай мне понадобятся заголовки для запроса. Их я скопирую из самого запроса на вкладке Headers. Для заголовков я возьму user-agent и accept.
Python:
headers = {
'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) '
'Chrome/98.0.4758.132 YaBrowser/22.3.1.892 Yowser/2.5 Safari/537.36',
'accept': '*/*'
}
Напишем функцию, которая будет получать JSON и извлекать из него данные: get_m3u8_list(url):
Python:
def get_m3u8_list(url):
req = requests.get(url=url, headers=headers)
video_data = req.json()
video_author = video_data['author']['name']
video_title = video_data['title']
dict_repl = ["/", "\\", "[", "]", "?", "'", '"', ":", "."]
for repl in dict_repl:
if repl in video_title:
video_title = video_title.replace(repl, "")
if repl in video_author:
video_author = video_author.replace(repl, "")
video_title = video_title.replace(" ", "_")
video_author = video_author.replace(" ", "_")
video_m3u8 = video_data['video_balancer']['m3u8']
return video_author, video_title, video_m3u8
Так как в названии канала и в названии видео могут содержаться всяческие символы, которые будут мешать при сохранении видео с нужным названием, а так же создания папки с названием канала, создадим список из наиболее часто встречающихся символов и пробежимся по названию канала и видео в цикле, где эти символы и заменим с помощью replace(). А после пробелы в названии канала и видео заменим на знак «_». Это будет нужно для того, чтобы ffmpeg при конвертации отработал корректно. Иначе он выдает ошибку о том, что видео для конвертации не найдено. Можно эту ошибку обойти. Но, чтобы не усложнять код, проще заменить пробелы. Ну и далее получаем ссылку на список плейлистов. После чего возвращаем из функции полученные значения. Вот код данного этапа:
Получение данных из JSON
Так как мы получаем список со ссылками на плейлисты, то нужно его исследовать. А вернее, то, что мы получаем. А получаем мы содержимое со ссылками, где последняя ссылка, это ссылка на видео самого высокого качества. Ее мы и будем брать для загрузки сегментов. Таким образом у нас отпадет необходимость в поиске видео самого высокого качества и в случае, если, к примеру, видео с разрешением 720p не окажется в списке, мы получим ссылку на самое максимально возможное качество для данного видео.
Список со ссылками на плейлисты
Получаем ссылку на плейлист
Итак, мы получили список с нужными нам данными. Теперь нужно получить список плейлистов и извлечь из него ссылку на нужный нам. В плейлисте содержится список видеосегментов, которые подгружаются при просмотре видео. И данный список нам будет очень нужен. Позже поймете зачем.
Создадим функцию get_link_from_m3u8(url_m3u8), которая получает на входе ссылку на список ссылок на плейлисты. А на выходе этой функции мы получим ссылку на нужный нам плейлист. Ниже приведен уже модифицированный код с добавленной в него функцией:
Получение ссылки на нужный плейлист
Ну, а теперь небольшие пояснения. Сохраняем полученные значения в текстовый файл, после, открываем его и загоняем построчно в список. Ну, а затем уже извлекаем из списка последний элемент. Возвращаем полученное значение для дальнейшего использования.
Получаем количество сегментов видео
Что же, теперь у нас есть ссылка на плейлист, в котором содержаться все имена сегментов, которые подгружаются в процессе воспроизведения. Нам нужно получить имя самого последнего сегмента и вычленить из него порядковый номер, для того, чтобы понимать, сколько сегментов для загрузки нужно будет всего. Создаем функцию get_segment_count(m3u8_link). На входе она получает ссылку на плейлист, а на выходе возвращает количество сегментов. Вот код с добавленной функцией:
Получение количества сегментов видео
Ну, а теперь пояснения. Тут все достаточно просто. Делаем запрос и получаем плейлист. Создаем словарь для того, чтобы в него добавлять полученные значения с именами видеосегментов. Заполняем в цикле список из запроса. После чего получаем -2 элемент. В -1 элементе содержится служебная информация. Далее разбиваем полученную строку и очищаем от ненужных нам символов. Ну, а далее получаем цифру из названия последнего сегмента. Это и будет искомое значение. Его мы и возвращаем из функции.
Получаем ссылку для загрузки видео
Теперь нужно получить ссылку для загрузки видео, в которую мы будем подставлять нужные значения и скачивать сегменты. Данная ссылка у нас уже есть. Она содержится в ссылке на плейлист. Нужно ее только очистить от всего лишнего. Поэтому создадим функцию, в которой это и сделаем. Назовем ее, к примеру, get_download_link(m3u8_link). На входе в нее будет передаваться ссылка на плейлист, очищаться и на выходе возвращаться уже очищенной. Вот код с данной функцией:
Получаем ссылку для загрузки видео
Загружаем сегменты видео
Теперь, когда у нас есть вся нужная информация, можно приступать к загрузке сегментов. Для этого я создам функцию get_download_segment(link, count), в которую на входе будет подаваться очищенная в предыдущей функции ссылка, и количество сегментов для загрузки. Возвращать данная функция ничего не будет. Она будет просто загружать сегменты видео. И код еще раз, уже с функцией загрузки сегментов:
Загрузка сегментов видео
Для того, чтобы не мусорить сегментами в той папке, где работает наш скрипт, создадим временную папку для загрузки в нее сегментов. Проверяем ее наличие, а если нет – создаем. Далее создаем цикл, который пробегается по диапазону с количеством сегментов. В этом цикле мы формируем нужную нам ссылку и загружаем сегмент на диск, в только что созданную папку. Чтобы не было скучно во время этого процесса, выведем принты в терминал о загрузке каждого сегмента и об полном ее окончании, когда уже все сегменты будут загружены.
Объединяем сегменты в одно видео формата ts и конвертируем в mp4
Чисто практически, да и в теории, можно оставить объединенное видео в формате ts. Оно вполне себе проигрывается с помощью проигрывателя. Но, мне не понравился небольшой глюк при проигрывании. Если я хочу видео перемотать, у него начинается рассинхронизация между звуком и видео. Можно подобрать, конечно, плеер, который будет это все корректно воспроизводить. Но проще видео конвертировать в нужный формат, а именно mp4. Создаем функцию merge_ts(author, title, count), на вход которой подаем название канала, название видео и количество сегментов загруженного видео для объединения. Далее уже будет представлен полный код загрузки и конвертации видео, а пояснения по последней функции я дам немного ниже:
Полный код для загрузки видео
А теперь пояснения. Открываем файл для записи в побайтовом режиме. После чего создаем цикл, в котором по очереди открываем и читаем все загруженные сегменты побайтово для добавления их с помощью shutil.copyfileobj в один файл для последующей записи. Ну и сохраняем файл в папке с сегментами, но с именем, которое уже было получено из JSON файла в самом начале.
Ну, а далее создаем папку с названием канала и запускаем конвертацию видео с помощью os.system, которая позволяет выполнять консольные команды. Нужно сказать, что я использую в данный момент Windows. В ОС Linux нужно будет воспользоваться функцией subprocess.
Теперь, после того, как файл конвертирован и сохранен, остается только прибраться в директории. Для этого сканируем папку с сегментами. Получаем список файлов и в цикле их все удаляем. После чего удаляем и саму папку.
В принципе все. Способ достаточно простой. Я думал, что будет сложнее. Кто знает, может быть с течением времени они что-то поменяют в коде и написанный мной скрипт перестанет работать. Но в данное время, все работает. Конечно же, те кто уже давно программирует на питоне, могут значительно улучшить данный код. Но, снова прошу вас меня сильно не пинать. Я только учусь программировать. А для новичков, вроде меня, для понимания общих принципов работы, данный код, думаю, будет полезен.
Сюда же, для большей универсальности кода, чтобы он мог работать под разными ОС, можно добавить определение платформы, на которой он запущен и в зависимости от этого менять разделители в путях к папкам и файлам. Так же, в зависимости от ОС вызывать терминал разными способами...
Спасибо за внимание! Надеюсь, что эта статься кому-то смогла помочь )
Последние темы в этом разделе:
- [Alex Erofeev] [Stepik] JavaScript: самый быстрый курс (2024)
- [Михаил Русаков] Написание лайфхаков на Python (2021)
- Пишем DDOS скрипт на Python
- [Саид Магомедов] Python. Микросервисы. Backend на FastAPI [Stepik] (2024)
- Как написать чат-бота на python
- Пишем скрипт по парсингу ответов из gdz.ru
- [Udemy] Кибербезопасность: тестирование на проникновение с помощью Python 3 (2022)
- [Udemy] [ENG] Продвинутый ИИ - глубокое обучение с подкреплением в Python (2024)
- Создание бесплатного API для генерации изображений, используя перехваченные запросы Flux
- [Андрей Сумин] [Stepik] Java с нуля до Junior + Подготовка к собеседованию (2024)