Пожалуйста, включите полный вывод 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. Вот дополнительная информация о проблеме: ...". Хотя некоторые проблемы могут быть старыми, новый пост в них часто вызывает быструю активность.
Люди хотят решать проблемы, и часто считают, что делают нам одолжение, разбивая свои большие проблемы (например, желание пропустить уже загруженные файлы) на конкретный запрос (например, попросить нас проверить, существует ли файл перед загрузкой страницы информации). Однако, что часто происходит, так это то, что они разбивают проблему на два шага: один простой, а другой невозможный (или крайне сложный). Затем мы сталкиваемся с очень сложным запросом, когда исходная проблема могла бы быть решена намного проще, например, путем записи идентификаторов загруженных видео в отдельный файл. Чтобы избежать этого, вы должны включить более широкий контекст, где это не очевидно. В частности, каждый запрос на новую функцию, который не состоит в добавлении поддержки для нового сайта, должен содержать сценарий использования, который объясняет, в какой ситуации отсутствующая функция была бы полезна.
Публикуйте только те функции, которые вам (или вашему недееспособному другу, с которым вы можете лично поговорить) необходимы. Не публикуйте функции только потому, что они кажутся хорошей идеей. Если они действительно полезны, они будут запрошены кем-то, кто ими пользуется.
Чтобы запустить youtube-dl как разработчик, вам не нужно ничего собирать. Просто выполните
python -m youtube_dl
Чтобы запустить тест, просто вызовите ваш выбор тестового запуска, или выполните файл теста напрямую; любой из следующих вариантов работает:
python -m unittest discover
python test/test_download.py
nosetests
См. пункт 6 нового раздела для понимания, как запустить тестовые испытания для конкретной ссылки.
Если вы хотите создать сборку youtube-dl самостоятельно, вам потребуется
Если вы хотите добавить поддержку для нового сайта, сначала убедитесь, что этот сайт не посвящён [нарушениям авторских прав](README.md#можете-додати-підтримку-для-цього-сайту-аниме-відео-або-сайту-що-показує- актуальні-фільми-без-коштів). youtube-dl не поддерживает такие сайты, поэтому запросы на добавление поддержки для них будут отклонены.
После того, как вы убедились, что этот сайт распространяет свои материалы законно, вы можете использовать этот быстрый список (предполагая, что ваш сервис называется yourextractor
):1. Создайте форк этого репозитория
2. Проверьте исходный код с помощью:
git clone git@github.com:YOUR_GITHUB_USERNAME/youtube-dl.git
Начните новый git-ветвь с помощью
cd youtube-dl
git checkout -b yourextractor
Начните с этого простого шаблона и сохраните его в 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)
}
Добавьте импорт в youtube_dl/extractor/extractors.py
. Это делает извлечитель доступным для использования, если класс заканчивается на IE
.
Запустите python test/test_download.py TestDownload.test_YourExtractor
. Это должно завершиться ошибкой сначала, но вы можете продолжать перезапускать его до тех пор, пока не закончите. Если вы решите добавить более одного теста, то переименуйте _TEST
в _TESTS
и сделайте его списком словарей. Тесты будут названы TestDownload.test_YourExtractor
, TestDownload.test_YourExtractor_1
, TestDownload.test_YourExtractor_2
, и т.д. Обратите внимание, что тесты с ключом only_matching
в словаре теста не учитываются.
Посмотрите на youtube_dl/extractor/common.py
для возможных вспомогательных методов и детального описания того, что должен и может вернуть ваш извлечитель. Добавьте тесты и код для столько свойств, сколько вам нужно.
Убедитесь, что ваш код следует кодировочным конвенциям youtube-dl и проверьте код с flake8: $ flake8 youtube_dl/extractor/yourextractor.py
Убедитесь, что ваш код работает под всеми Python версиями, поддерживаемыми youtube-dl, а именно 2.6, 2.7, и 3.2+.
Когда тесты проходят, добавьте новые файлы и закоммитьте их и запушьте результат, как это:
$ 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
Наконец, создайте запрос на слияние. Мы затем проверим и объединим его.
В любом случае, большое спасибо за ваши вклады!
В этом разделе представлены руководства по написанию идиоматического, надёжного и будущее-ориентированного кода извлечения.Извлекатели по своей природе очень хрупки, так как они зависят от структуры данных, предоставленных третьими сторонами, которые находятся вне вашего контроля, и эта структура часто меняется. В качестве разработчика извлечения ваша задача не только написать код, который будет правильно извлекать ссылки на медиа и метаданные, но также минимизировать зависимость от структуры данных источника и даже сделать код способным предвидеть потенциальные будущие изменения и быть готовым к ним. Это важно, так как это позволит извлечению не ломаться при незначительных изменениях структуры данных, что позволит старым версиям 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
для получения дополнительных удобных функций.
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 )