Всем привет! Пишу впервые, хоть и читаю Хабр с 2012 года. Буду рад любой обратной связи. Поехали.
Предыстория
VK — хранилище интересного мне видеоконтента. Относительно недавно просмотр видео на бюджетных устройствах (особенно в приложении) стал невозможен по ряду причин:
- Постоянные ошибки
- Низкая частота кадров при качестве 720p и выше
- Графические артефакты при качестве 480p и ниже
Я решил воспользоваться безотказным методом — скачивать видео и смотреть их локально. Однако, найти ссылки на mp4 файлы в исходниках desktop-версии VK мне не удалось. Несколько лет назад — удавалось. Видимо теперь всё работает через более хитрый стриминг. Возможно по этой же причине более не работают сторонние сервисы для скачивания видео.
Потратив немного времени, я выяснил, что ссылки на файлы можно выудить из мобильной версии VK. Каждый раз вытаскивать их руками, путаясь в качестве видео, оказалось неудобно. Так и зародилась идея браузерного расширения: хотелось бы, чтобы при переходе на страницу с любым видео, под плеером отображались ссылки для скачивания его в любом из доступных качеств.
Как скачивать файлы с помощью Python
Реализация
Для начала, создадим manifest.json — файл, содержащий информацию о расширении. Помимо обязательных полей, добавим в него поле content_scripts , содержащее следующее правило: при переходе на любую страницу на домене m.vk.com и полной загрузке DOM исполнить код, находящийся в файле content-script.js. Такой код называется встраиваемым скриптом. Манифест может содержать огромное количество разнообразных полей. Подробная документация по этому поводу — здесь.
// manifest.json < «manifest_version»: 3, «name»: «VK Video Downloader», «version»: «1.0.0», «action»: <>, «content_scripts»: [ < «js»: [«content-script.js»], «matches»: [«https://m.vk.com/*»], «run_at»: «document_idle» >] >
// content-script.js alert(‘Hello, World!’);
Перейдя на страницу любого видео и взглянув на HTML-дерево, мы увидим примерно следующее:
Нас интересуют значения аттрибутов src тегов , отвечающих за mp4 файлы. И я не просто так отметил url-параметр type в каждом из них. Именно он ответственен за качество видео. Единожды скачав все возможные вариации одного видео, я вывел таблицу соответствия:
Значение параметра type
Да, 144p выбивается из общей логики и имеет тип 4. Возможно отголоски какого-то легаси, а возможно я просто чего-то не знаю и кто-нибудь просветит меня в комментариях 🙂
Реализуем функцию, собирающую и возвращающую нужные нам данные в удобном для дальнейшей обработки формате:
// content-script.js function getVideoSources() < const sourceTags = document.querySelectorAll( ‘video source[type=»video/mp4″]’ ); let videoSources = <>; for (const tag of sourceTags) < if (tag.src.includes(‘ videoSources[‘144p’] = tag.src; >else if (tag.src.includes(‘ videoSources[‘240p’] = tag.src; >else if (tag.src.includes(‘ videoSources[‘360p’] = tag.src; >else if (tag.src.includes(‘ videoSources[‘480p’] = tag.src; >else if (tag.src.includes(‘ videoSources[‘720p’] = tag.src; >else if (tag.src.includes(‘ videoSources[‘1080p’] = tag.src; >else if (tag.src.includes(‘ videoSources[‘1440p’] = tag.src; >else if (tag.src.includes(‘ videoSources[‘2160p’] = tag.src; >> return videoSources; > console.log(getVideoSources());
Теперь, перезагрузив расширение и открыв страницу любого видео, мы увидим в консоли браузера нечто подобное (количество полей будет варьироваться в зависимости от максимального качества видео):
Лучшая программа для скачивания видео файлов. Обзор Mediaget
Казалось бы, задача практически решена, однако именно на этом этапе разработки, я заметил нюанс, заставивший меня поломать голову.
При вводе URL страницы с видео в адресную строку и нажатии Enter скрипт срабатывал. При переходе на страницу с другой страницы VK — не срабатывал, однако стоило её перезагрузить — он всё же срабатывал.
Насколько мне удалось выяснить, дело в том, что при навигации по VK далеко не всегда происходит полноценный переход на новую страницу. Во многих случаях просто перестраивается DOM, что не является условием срабатывания встраиваемого скрипта.
Придётся действовать иначе. Будем отслеживать изменения DOM в реальном времени и извлекать данные лишь в том случае, если находимся на странице видео (путь начинается с /video- ) и заметили появление в документе контейнера видеоплеера (имеет класс VideoPage__video ). Поможет нам в этом такая замечательная вещь, как MutationObserver. Также, стоит учитывать то, что отрисоваться контейнер может далеко не сразу. Поэтому, при переходе на страницу с видео, будем искать его каждые 100 мс, пока не найдём.
// content-script.js let lastUrl = location.href; new MutationObserver(() => < if (location.href !== lastUrl) < lastUrl = location.href; >if (location.pathname.includes(‘/video-‘)) < const checker = setInterval(() => < if ( document.querySelector(‘div.VideoPage__video’) ) < clearInterval(checker); getVideoSources(); >>, 100); > >).observe(document, < subtree: true, childList: true >); function getVideoSources()
Замечательно. Теперь, стоит плееру появиться на странице (неважно каким образом вы на эту страницу попали), в консоль выводятся нужные нам данные. Давайте реализуем функционал для отображения их непосредственно на странице, немного подогнав под вёрстку VK:
// content-script.js function createDownloadPanel(videoSources) < const label = document.createElement(‘span’); label.innerText = ‘Скачать:’; label.style.marginRight = ‘2px’; const panel = document.createElement(‘div’); panel.id = ‘vkVideoDownloaderPanel’; panel.style.margin = ‘8px 12px’; panel.appendChild(label); for (const [quality, url] of Object.entries(videoSources)) < const aTag = document.createElement(‘a’); aTag.href = url; aTag.innerText = quality; aTag.style.margin = ‘0 2px’; panel.appendChild(aTag); >return panel; > function showPanel(panel)
Чуть позже я немного доработал расширение:
- Добавил обработку видео, встроенных со сторонних сайтов (в контейнере плеера в таком случае находится не , а )
- Исправил баги, из-за которых, функция отвечающая за отрисовку панели для скачивания n-ое количество раз отрабатывала вхолостую, ничего не отрисовывая
- Добавил иконки
- Дополнил manifest.json
Взглянуть на финальную версию и воспользоваться ей можно перейдя на мой GitHub. Уже получил несколько благодарностей на почту за публикацию этого расширения. Может будет полезно и вам.
Спасибо, что дочитали до конца.
Источник: habr.com
Telegram-бот на Python + AIOGram для скачивания видео из YouTube
Сегодня мы разберем как сделать телеграм-бота для скачивания видео из YouTube. Часто бывает, что мы куда-то едем и нужно скачать пару аудио версий видео, но платить возможности нет. Чтобы избежать трат, мы прибегнем к библиотеке pyTube (для скачивания видео) и AIOGram (для взаимодействия с API Telegram).
Я дам удобный шаблон для работы с AIOGram, где уже будет структурированный проект. Хотя для такого маленького проекта можно все собрать и в один файл, мы всё же оставим место для расширения нашего помощника.
Сразу обозначу, что мы не будем разжёвывать материал досконально. Но я оставлю ссылки на более подробную информацию о тех моментах, на которых сам спотыкался.
Подготовка проекта в PyCharm
Создаем проект в PyCharm и устанавливаем библиотеки. Скачиваем шаблон телеграм-бота с GutHub.
Устанавливаем модули, с которыми будем работать:
pip install aiogram pytube
Вариант для macOS:
pip3 install aiogram pytube
Pytube: скачиваем Youtube видео с помощью Python
Pytube это библиотека для скачивания видео с Youtube. Как сказано в документации, у неё нет сторонних зависимостей и она построена на стандартной библиотеке.
Установка
Установить пакет можно с помощью менеджера пакетов pip:
pip install pytube
Эта команда найдёт пакет в репозитории, скачает его и установит на локальную машину. Вывод команды будет примерно таким:
Collecting pytube Downloading pytube-6.2.2-py2-none-any.whl Installing collected packages: pytube Successfully installed pytube-6.2.2
Работаем с pytube
После завершения установки откройте консоль python и импортируйте пакет pytube:
import pytube
Класс YouTube представляет экземпляр YouTube-сессии, поэтому его нужно инициализировать так:
yt = pytube.YouTube(‘https://www.youtube.com/watch?v=xtZOnyYu16U’)
После этого в переменной yt будет храниться вся информация о переданном видео, к примеру название файла:
fn = yt.filename
Как известно, чтобы получить значение переменной в консоли python, нужно ввести её наименование и нажить кнопку Ввод на клавиатуре:
fn
Вы должны увидеть следующее:
u’Stoto — Late Night (Original Mix)’
Всё довольно очевидно — вы видите имя файла от переданной ссылки на видео при создании экземпляра класса в его методе YouTube.__init__.
Также нам доступен атрибут video_id, который определяется при создании экземпляра класса. Можно вывести его так:
Доступные для скачивания видео можно получить методом get_videos:
videos = yt.get_videos()
Выведем в цикле каждое из них:
for v in videos: print(v)
Для моего видео вывод будет таким:
Тип каждого объекта получим так:
for v in videos: print(type(v))
Вывод должен быть таким:
Класс pytube.models.Video используется для создания отдельных экземпляров видео с дальнейшим скачиванием.
Первый экземпляр можно получить по его индексу:
first_video = videos[0] print(first_video)
Video имеет много атрибутов, таких как filename, url, extension, video_codec, audio_codec, audio_bitrate, resolution и т.д.
Расширение видео получим так:
first_video.extension
‘3gp’
Качество видео:
quality = first_video.resolution
print(quality)
‘144p’
Битрейт:
audio_bitrate = first_video.audio_bitrate video_bitrate = first_video.video_bitrate print(audio_bitrate) print(video_bitrate)
Скачать видео также просто:
Выбранное видео будет загружено в папку /Users/oltjano/Desktop
А если вам нужно перезаписать загруженное ранее видео, присвойте переменной force_overwrite значение True:
Скачиваем видео определённого формата
Начнём с начала. Перезапустите консоль python и введите:
import pytube video_link = ‘https://www.youtube.com/watch?v=8ZpVwAeLzm4’
Создадим Youtube сессию и запросим доступные форматы:
yt = pytube.YouTube(video_link) videos = yt.videos
Используя метод get можно отфильтровать видео по формату и качеству:
video = yt.get(‘mp4’, ‘720p’)
Если такое видео будет доступно, в переменной появятся ссылки на него, иначе — будет выведена ошибка.
Итак, у нас нет ошибки, значит, видео можно скачать. Зададим путь для загруженного файла и загрузим видео:
path = ‘/Users/Oltjano/Desktop’ video.download(path)
Источник: tehnojam.ru