1 В избранное 0 Ответвления 0

OSCHINA-MIRROR/mirrors-youtube-downloader

Клонировать/Скачать
CONTRIBUTING.md 38 КБ
Копировать Редактировать Web IDE Исходные данные Просмотреть построчно История
Отправлено 26.05.2025 06:50 c2e176d

Пожалуйста, включите полный вывод youtube-dl при запуске с флагом -v, то есть добавьте флаг -v к вашей команде, скопируйте весь вывод и вставьте его в тело сообщения об ошибке, обрамив тройными обратными кавычками для лучшего форматирования. Вывод должен выглядеть примерно так:

$ youtube-dl -v <ваша команда>
[отладка] Системная конфигурация: []
[отладка] Конфигурация пользователя: []
[отладка] Аргументы командной строки: [u'-v', u'https://www.youtube.com/watch?v=BaW_jenozKcj']
[отладка] Кодировки: локаль cp1251, файловая система mbcs, вывод cp866, предпочтения cp1251
[отладка] Версия youtube-dl 2015.12.06
[отладка] Git HEAD: 135392e
[отладка] Python версия 2.6.6 - Windows-2003Server-5.2.3790-SP2
[отладка] exe версии: ffmpeg N-75573-g1d0487f, ffprobe N-75573-g1d0487f, rtmpdump 2.4
[отладка] Мапа прокси: {}
...

Не публикуйте скриншоты подробных логов; только обычный текст допустим.

Вывод (включая первые строки) содержит важную отладочную информацию. Сообщения об ошибках без полного вывода часто не воспроизводимы и поэтому не решаются в кратчайшие сроки, если вообще решаются.

Пожалуйста, перечитайте ваше сообщение об ошибке, чтобы избежать нескольких распространённых ошибок (вы можете и должны использовать это как проверочный список):

Достаточно ли описательна сама ошибка?Часто мы получаем сообщения об ошибках, которые не можем расшифровать. Хотя в большинстве случаев мы в конечном итоге получаем необходимую информацию после нескольких запросов, это накладывает дополнительную нагрузку на наши ресурсы. Многие вкладчики, включая меня, не являются носителями языка, поэтому мы можем неправильно интерпретировать некоторые части.Поэтому, пожалуйста, подробно опишите, какой функциональный элемент вы хотите запросить или какую ошибку вы хотите исправить. Убедитесь, что это очевидно:

  • Что за проблема
  • Как она может быть исправлена
  • Как будет выглядеть ваше предложенное решение

Если ваш отчёт короче двух строк, он почти наверняка недостаточен, что затрудняет для нас ответ на него. Мы часто слишком вежливы, чтобы закрывать такие сообщения сразу, но недостающая информация делает неправильное толкование вероятным. Как вкладчик, я часто раздражаюсь из-за таких сообщений, поскольку единственный возможный способ для меня двигаться вперёд — это снова и снова запрашивать уточнения.Для отчётов об ошибках это означает, что ваш отчёт должен содержать полный вывод youtube-dl при вызове с флагом -v. Сообщение об ошибке, которое вы получаете для (большинства) ошибок, даже указывает на это, но вы не поверите, сколько наших отчётов об ошибках не содержат этой информации. Если ваш сервер имеет несколько IP-адресов или вы подозреваете цензуру, добавление --call-home может быть хорошей идеей для получения дополнительной диагностики. Если ошибка ERROR: Unable to extract ... и вы не можете воспроизвести её из нескольких стран, добавьте --dump-pages (предупреждение: это приведёт к значительному объёму вывода, перенаправьте его в файл log.txt с помощью добавления >log.txt 2>&1 к вашей команде) или загрузите файлы .dump, которые вы получите при добавлении --write-pages куда-то.Запросы поддержки сайта должны содержать пример URL. Пример URL — это URL, который вы можете захотеть скачать, например https://www.youtube.com/watch?v=BaW_jenozKc. На этом URL должен присутствовать явный видеоролик. За исключением очень специфических обстоятельств, главная страница видеосервиса (например, https://www.youtube.com/) не является примером URL.

Используете ли вы последнюю версию?

Перед тем как сообщить о проблеме, введите youtube-dl -U. Это должно сообщить вам, что вы используете последнюю версию. Около 20% сообщений, которые мы получаем, уже были исправлены, но люди используют устаревшие версии. Это касается и запросов на новые функции.

Не была ли проблема уже документирована?

Убедитесь, что кто-то ещё не открыл ту же проблему, которую вы пытаетесь открыть. Поищите в верхней части окна или просмотрите GitHub Issues этого репозитория. Если проблема уже открыта, не стесняйтесь написать что-то вроде "Это также затрагивает меня, версия 2015.01.01. Вот дополнительная информация о проблеме: ...". Хотя некоторые проблемы могут быть старыми, новый пост в них часто вызывает быструю активность.

Почему существующие опции недостаточны?Перед тем как запросить новую функцию, пожалуйста, посмотрите на список поддерживаемых опций. Многие запросы на новые функции уже реализованы! Пожалуйста, обязательно укажите вашу работу в отчёте о проблеме и подробно объясните, как существующие похожие опции не решают вашу проблему.### Достаточно ли контекста в вашем отчете о баге?

Люди хотят решать проблемы, и часто считают, что делают нам одолжение, разбивая свои большие проблемы (например, желание пропустить уже загруженные файлы) на конкретный запрос (например, попросить нас проверить, существует ли файл перед загрузкой страницы информации). Однако, что часто происходит, так это то, что они разбивают проблему на два шага: один простой, а другой невозможный (или крайне сложный). Затем мы сталкиваемся с очень сложным запросом, когда исходная проблема могла бы быть решена намного проще, например, путем записи идентификаторов загруженных видео в отдельный файл. Чтобы избежать этого, вы должны включить более широкий контекст, где это не очевидно. В частности, каждый запрос на новую функцию, который не состоит в добавлении поддержки для нового сайта, должен содержать сценарий использования, который объясняет, в какой ситуации отсутствующая функция была бы полезна.

Содержит ли проблема только одну проблему?Некоторые из наших пользователей считают, что существует ограничение на количество проблем, которые они могут или должны открыть. Ограничения на количество проблем, которые они могут или должны открыть, не существует. Хотя может показаться привлекательным выгрузить все ваши проблемы в одну заявку, это означает, что кто-то, кто решает одну из ваших проблем, не сможет отметить заявку как закрытую. Обычно, когда вы отчитываетесь о целой серии проблем, заявка остаётся нерешённой, поскольку никто не хочет атаковать этот монстр, пока кто-то милосердно не разделит проблему на несколько.В частности, каждая заявка на поддержку сайта должна касаться только одного сайта (обычно под общим доменом, но всегда использующего одну и ту же технологию backend). Не просите поддержки для видео пользователей Vimeo, подкастов Белого дома и страниц Google Plus в одной заявке. Также убедитесь, что вы не публикуете отчеты о багах вместе с запросами на новые функции. Как правило, запрос на новую функцию не должен включать выводы youtube-dl, которые не имеют непосредственного отношения к самой функции. Не публикуйте отчеты о сетевых ошибках вместе с запросом на новую видео-услугу.

Будет ли кто-то нуждаться в этой функции?

Публикуйте только те функции, которые вам (или вашему недееспособному другу, с которым вы можете лично поговорить) необходимы. Не публикуйте функции только потому, что они кажутся хорошей идеей. Если они действительно полезны, они будут запрошены кем-то, кто ими пользуется.

Связана ли ваша проблема с youtube-dl?Может показаться странным, но некоторые отчеты о багах, которые мы получаем, совершенно не связаны с youtube-dl и касаются другого, или даже собственного, приложения отчетчика. Убедитесь, что вы действительно используете youtube-dl. Если вы используете графический интерфейс для youtube-dl, отправьте отчет о баге разработчику самого приложения, предоставляющего этот интерфейс. С другой стороны, если ваш графический интерфейс для youtube-dl не работает каким-то образом, и вы считаете, что это связано с youtube-dl, безусловно, отправьте отчет о баге.

ПОВЕРХНЯЧНІ НАВЧАННЯБольшинство пользователей не имеют необходимости собирать youtube-dl и могут скачать сборку или получить её от своей дистрибуции.

Чтобы запустить youtube-dl как разработчик, вам не нужно ничего собирать. Просто выполните

python -m youtube_dl

Чтобы запустить тест, просто вызовите ваш выбор тестового запуска, или выполните файл теста напрямую; любой из следующих вариантов работает:

python -m unittest discover
python test/test_download.py
nosetests

См. пункт 6 нового раздела для понимания, как запустить тестовые испытания для конкретной ссылки.

Если вы хотите создать сборку youtube-dl самостоятельно, вам потребуется

  • python
  • make (только GNU make поддерживается)
  • pandoc
  • zip
  • nosetests

Добавление поддержки для нового сайта

Если вы хотите добавить поддержку для нового сайта, сначала убедитесь, что этот сайт не посвящён [нарушениям авторских прав](README.md#можете-додати-підтримку-для-цього-сайту-аниме-відео-або-сайту-що-показує- актуальні-фільми-без-коштів). youtube-dl не поддерживает такие сайты, поэтому запросы на добавление поддержки для них будут отклонены.

После того, как вы убедились, что этот сайт распространяет свои материалы законно, вы можете использовать этот быстрый список (предполагая, что ваш сервис называется yourextractor):1. Создайте форк этого репозитория 2. Проверьте исходный код с помощью:

    git clone git@github.com:YOUR_GITHUB_USERNAME/youtube-dl.git
  1. Начните новый git-ветвь с помощью

     cd youtube-dl
     git checkout -b yourextractor
  2. Начните с этого простого шаблона и сохраните его в youtube_dl/extractor/yourextractor.py:

    # кодировка: utf-8
    from __future__ import unicode_literals
    
    from .common import InfoExtractor
    
    класс YourExtractorIE(InfoExtractor):
        _VALID_URL = r'https?://(?:www\.)?yourextractor\.com/watch/(?P<id>[0-9]+)'
        _ТЕСТ = {
            'url': 'https://yourextractor.com/watch/42',
            'md5': 'TODO: md5 сумма первых 10241 байта видеофайла (используйте --test)',
            'info_dict': {
                'id': '42',
                'ext': 'mp4',
                'title': 'Название видео здесь',
                'thumbnail': r're:^https?://.*\.jpg$',
                # TODO более свойств, либо как:
                # * Значение
                # * MD5 контрольная сумма; начните строку с md5:
                # * Регулярное выражение; начните строку с re:
                # * Любое значение типа Python (например int или float)
            }
        }
    
        def _real_extract(self, url):
            video_id = self._match_id(url)
            webpage = self._download_webpage(url, video_id)
    
            # TODO более кода следует здесь, например ...
            title = self._html_search_regex(r'<h1>(.+?)</h1>', webpage, 'title')
    ```            return {
                'id': video_id,
                'title': title,
                'description': self._og_search_description(webpage),
                'uploader': self._search_regex(r'<div[^>]+id="uploader"[^>]*>([^<]+)<', webpage, 'uploader', fatal=False),
                # TODO добавьте больше свойств (см. youtube_dl/extractor/common.py)
            }
  3. Добавьте импорт в youtube_dl/extractor/extractors.py. Это делает извлечитель доступным для использования, если класс заканчивается на IE.

  4. Запустите python test/test_download.py TestDownload.test_YourExtractor. Это должно завершиться ошибкой сначала, но вы можете продолжать перезапускать его до тех пор, пока не закончите. Если вы решите добавить более одного теста, то переименуйте _TEST в _TESTS и сделайте его списком словарей. Тесты будут названы TestDownload.test_YourExtractor, TestDownload.test_YourExtractor_1, TestDownload.test_YourExtractor_2, и т.д. Обратите внимание, что тесты с ключом only_matching в словаре теста не учитываются.

  5. Посмотрите на youtube_dl/extractor/common.py для возможных вспомогательных методов и детального описания того, что должен и может вернуть ваш извлечитель. Добавьте тесты и код для столько свойств, сколько вам нужно.

  6. Убедитесь, что ваш код следует кодировочным конвенциям youtube-dl и проверьте код с flake8: $ flake8 youtube_dl/extractor/yourextractor.py

  7. Убедитесь, что ваш код работает под всеми Python версиями, поддерживаемыми youtube-dl, а именно 2.6, 2.7, и 3.2+.

  8. Когда тесты проходят, добавьте новые файлы и закоммитьте их и запушьте результат, как это:

    $ git add ...
    $ git commit -m 'Add YourExtractor'
    $ git push origin master
    $ git add youtube_dl/extractor/extractors.py
    $ git add youtube_dl/extractor/yourextractor.py
    $ git commit -m '[yourextractor] Добавить новый извлечённый файл'
    $ git push origin yourextractor
  9. Наконец, создайте запрос на слияние. Мы затем проверим и объединим его.

В любом случае, большое спасибо за ваши вклады!

Правила написания кода для youtube-dl

В этом разделе представлены руководства по написанию идиоматического, надёжного и будущее-ориентированного кода извлечения.Извлекатели по своей природе очень хрупки, так как они зависят от структуры данных, предоставленных третьими сторонами, которые находятся вне вашего контроля, и эта структура часто меняется. В качестве разработчика извлечения ваша задача не только написать код, который будет правильно извлекать ссылки на медиа и метаданные, но также минимизировать зависимость от структуры данных источника и даже сделать код способным предвидеть потенциальные будущие изменения и быть готовым к ним. Это важно, так как это позволит извлечению не ломаться при незначительных изменениях структуры данных, что позволит старым версиям youtube-dl продолжать работать. Хотя эта проблема легко решается выпуском новой версии youtube-dl с внесённым исправлением, все предыдущие версии становятся неработоспособными во всех репозиториях и пакетах дистрибутивов, которые могут не быть такими быстрыми в получении обновления от нас. Безусловно, некоторые дистрибутивы без постоянных выпусков могут никогда не получить обновление.### Обязательные и необязательные метаполя

Для успешного извлечения youtube-dl полагается на метаданные, которые ваш извлечённый файл извлекает и предоставляет youtube-dl, выраженные в виде информационного словаря или просто info dict. Только следующие метаполя в info dict считаются обязательными для успешного процесса извлечения youtube-dl:

  • id (идентификатор медиа)
  • title (название медиа)
  • url (URL для загрузки медиа) или formats

В действительности только последний вариант является технически обязательным (то есть, если вы не можете определить местоположение для загрузки медиа, извлечение не имеет смысла). Но по соглашению youtube-dl также считает id и title обязательными. Таким образом, вышеупомянутые метаполя являются критическими данными, без которых извлечение не имеет смысла, и если любое из них не может быть извлечено, то извлечённый файл считается полностью сломанным. Любое поле помимо упомянутых считается необязательным. Это означает, что извлечение должно быть толерантным к ситуациям, когда источники для этих полей могут быть недоступны (даже если они всегда доступны в данный момент), и будущепroof, чтобы не нарушить извлечение общих обязательных полей.#### Пример

Предположим, что у вас есть словарь источников meta, который вы получили в виде JSON с HTTP-запросом, и он имеет ключ summary:

meta = self._download_json(url, video_id)

Предположим, что в данный момент структура meta выглядит следующим образом:

{
    ...
    "summary": "some fancy summary text",
    ...
}

Предположим, что вы хотите извлечь summary и поместить его в результирующий словарь info как description. Поскольку description является необязательным мета-полем, вы должны быть готовы к тому, что этот ключ может отсутствовать в словаре meta, поэтому вы должны извлекать его следующим образом:

description = meta.get('summary')  # верно

а не так:

description = meta['summary']  # неверно

Второй вариант прервёт процесс извлечения с ошибкой KeyError, если summary исчезнет из meta в будущем, тогда как первый вариант продолжит извлечение с description установленным в None, что вполне допустимо (помните, что None эквивалентен отсутствию данных).

Аналогично, вы должны передать fatal=False, когда извлекаете необязательные данные с веб-страницы с помощью _search_regex, _html_search_regex или подобных методов, например:

description = self._search_regex(
    r'<span[^>]+id="title"[^>]*>([^<]+)<',
    webpage, 'description', fatal=False)

С fatal установленным в False, если _search_regex не сможет извлечь description, он выдаст предупреждение и продолжит извлечение.

Вы также можете передать default=<some fallback value>, например:```python description = self._search_regex( r'<span[^>]+id="title"[^>]*>([^<]+)<', webpage, 'описание', default=None)


В случае неудачи этот код продолжит извлечение с `описание` установленным в `None`. Это полезно для метаполей, которые могут присутствовать или отсутствовать.

### Предоставьте резервные вариантыПри извлечении метаданных попытайтесь делать это из нескольких источников. Например, если `title` присутствует в нескольких местах, попытайтесь извлечь его из как минимум некоторых из них. Это делает процесс более устойчивым к изменениям в будущем, если некоторые из источников станут недоступными.

#### Пример

Предположим, что `meta` из предыдущего примера имеет поле `title`, и вы собираетесь его извлечь. Поскольку `title` является обязательным метаданным, вы должны закончить что-то вроде:

```python
title = meta['title']

Если title исчезнет из meta в будущем из-за изменений на стороне хостера, извлечение не удастся, так как title является обязательным. Это ожидаемо.

Предположим, что у вас есть другой источник, из которого вы можете извлечь title, например og:title HTML метаданные страницы. В этом случае вы можете предоставить сценарий резервного варианта:

title = meta.get('title') or self._og_search_title(webpage)

Этот код попытается извлечь из meta сначала, и если это не удастся, он попытается извлечь og:title из webpage.


#### Не захватывайте группы, которые вы не используете

Захватывающая группа должна быть индикатором того, что она используется где-то в коде. Любая группа, которая не используется, должна быть незахватывающей.

##### Пример

Не захватывайте имя атрибута `id` здесь, так как вы не можете использовать его ни для чего.

Правильно:

```python
r'(?:id|ID)=(?P<id>\d+)'

Неправильно:

r'(id|ID)=(?P<id>\d+)'

Сделайте регулярные выражения расслабленными и гибкими

Когда вы используете регулярные выражения, попытайтесь писать их размытыми, расслабленными и гибкими, игнорируя незначительные части, которые более вероятно изменятся, позволяя как одинарные, так и двойные кавычки для заключенных значений и так далее.

Пример

Предположим, что вам нужно извлечь title из следующего HTML кода:

<span style="position: absolute; left: 910px; width: 90px; float: right; z-index: 9999;" class="title">some fancy title</span>

Код для этой задачи должен выглядеть примерно так:

title = self._search_regex(
    r'<span[^>]+class="title"[^>]*>([^<]+)', webpage, 'title')

Или даже лучше:

title = self._search_regex(
    r'<span[^>]+class=(["\'])title\1[^>]*>(?P<title>[^<]+)',
    webpage, 'title', group='title')

Обратите внимание, как вы терпимо относитесь к потенциальным изменениям в значении атрибута style или переходу от использования двойных кавычек к одинарным для атрибута class. Код точно не должен выглядеть так:```python title = self._search_regex( r'(.*?)', webpage, 'название', group='title')


### Политика длинных строк

Существует мягкий лимит на то, чтобы длина строк кода не превышала 80 символов. Это означает, что он должен соблюдаться, если это возможно, и если это не ухудшает читаемость и поддержку кода.

Например, вы **никогда** не должны разделять длинные строковые литералы, такие как URL-адреса или другие часто копируемые сущности, на несколько строк, чтобы соответствовать этому лимиту:

Правильно:

```python
'https://www.youtube.com/watch?v=FqZTN594JQw&list=PLMYEtVRpaqY00V9W81Cwmzp6N6vZqfUKD4'

Неправильно:

'https://www.youtube.com/watch?v=FqZTN594JQw&list='
'PLMYEtVRpaqY00V9W81Cwmzp6N6vZqfUKD4'

Встроенные значения

Извлечение переменных допустимо для уменьшения дублирования кода и улучшения читаемости сложных выражений. Однако вы должны избегать извлечения переменных, которые используются только один раз и перемещения их в противоположные части файла-извлечения, что затрудняет чтение линейного потока.

Пример

Правильно:

title = self._html_search_regex(r'<title>([^<]+)</title>', webpage, 'название')

Неправильно:

TITLE_RE = r'<title>([^<]+)</title>'
# ...несколько строк кода...
title = self._html_search_regex(TITLE_RE, webpage, 'название')

Сжатие запасных значений

Множество запасных значений может быстро стать избыточным. Сжимайте несколько запасных значений в одно выражение с помощью списка шаблонов.#### Пример

Хорошо:

description = self._html_search_meta(
    ['og:description', 'description', 'twitter:description'],
    webpage, 'description', default=None)

Избыточно:

description = (
    self._og_search_description(webpage, default=None)
    or self._html_search_meta('description', webpage, default=None)
    or self._html_search_meta('twitter:description', webpage, default=None))

Методы, поддерживающие список шаблонов: _search_regex, _html_search_regex, _og_search_property, _html_search_meta.

Заключительные скобки

Всегда перемещайте заключительные скобки после последнего аргумента.

Пример

Правильно:

    lambda x: x['ResultSet']['Result'][0]['VideoUrlSet']['VideoUrl'],
    list)

Некорректно:

    lambda x: x['ResultSet']['Result'][0]['VideoUrlSet']['VideoUrl'],
    list,
)

Используйте удобные функции преобразования и парсинга

Оберните все извлеченные числовые данные в безопасные функции из youtube_dl/utils.py: int_or_none, float_or_none. Используйте их для преобразования строк в числа.

Используйте url_or_none для безопасной обработки URL.

Используйте try_get для безопасного извлечения метаданных из распарсенного JSON.

Используйте unified_strdate для унифицированного извлечения upload_date или любого поля метаданных в формате YYYYMMDD, unified_timestamp для унифицированного извлечения timestamp, parse_filesize для извлечения filesize, parse_count для извлечения полей метаданных типа счетчик, parse_resolution, parse_duration для извлечения duration, parse_age_limit для извлечения age_limit.Изучите youtube_dl/utils.py для получения дополнительных удобных функций.

Дополнительные примеры

Безопасное извлечение необязательного описания из распарсенного JSON
description = try_get(response, lambda x: x['result']['video'][0]['summary'], compat_str)
Безопасное извлечение дополнительных необязательных метаданных
video = try_get(response, lambda x: x['result']['video'][0], dict) or {}
description = video.get('summary')
duration = float_or_none(video.get('durationMs'), scale=1000)
view_count = int_or_none(video.get('views'))

Опубликовать ( 0 )

Вы можете оставить комментарий после Вход в систему

1
https://api.gitlife.ru/oschina-mirror/mirrors-youtube-downloader.git
git@api.gitlife.ru:oschina-mirror/mirrors-youtube-downloader.git
oschina-mirror
mirrors-youtube-downloader
mirrors-youtube-downloader
master