Побег от алгоритма YouTube
Я люблю смотреть видео на YouTube, осязаемым образом улучшающие мою жизнь. К сожалению, алгоритм YouTube с этим не согласен. Он любит кормить меня кликбэйтом и прочим мусором.
Всё это неудивительно: алгоритм отдаёт приоритет кликам и времени просмотра.
Поэтому я поставил перед собой задачу: Смогу ли я написать код, который автоматически будет находить ценные видео, избавив меня от привязанности к алгоритму YouTube?
Вот так всё и началось.
Оптимально выстроенные планы
Я начал с визуализации того, что должен делать мой инструмент. Мне нужна была программа, которая будет (i) ранжировать видео на основании вероятной релевантности для меня и (ii) автоматически отправлять мне предлагаемые видео, из которых я смогу выбирать.
Я решил, что смогу серьёзно повысить продуктивность, если буду пакетно выбирать наборы видео для просмотра на каждую неделю и избавлюсь от необходимости бесконечного скроллинга YouTube.
Я знал, что нужно заставить YouTube API получать информацию о видео (что такое API?). Затем я создам формулу, которая будет обрабатывать эту информацию для ранжирования видео. На последнем этапе я запланировал создавать при помощи AWS Lambda автоматическое письмо на мой адрес, содержащее видео с наивысшим рейтингом.
Однако в конечном итоге всё получилось не совсем так.
(Если не хотите читать статью и перейти прямиком к готовому коду, то вам сюда.)
Исследуем YouTube API
Я хотел найти метрики, которые можно использовать для ранжирования видео по их вероятной интересности для меня.
Я изучил документацию YouTube, выложенную здесь, и понял, что можно получать информацию на уровне видео (название, время публикации, количество просмотров, картинка-превью и т.д.) и на уровне канала (количество подписчиков, комментарии, просмотры, плейлисты канала и т.д.).
Когда я увидел это, у меня появилась уверенность в том, что можно использовать эту информацию для задания метрики и ранжирования видео.
Я получил ключ API через консоль разработчика здесь и скопировал его в мой скрипт на Python.
Это позволяет инициализировать API такими строками кода:
# Call the YouTube API
api_key = ‘AIzpSyAq3L9DiPK0KxrGBbdY7wNN7kfPbm_hsPg’ # Enter your own API key – this one won’t work
youtube_api = build(‘youtube’, ‘v3’, developerKey = api_key)
results = youtube_api.search().list(q=search_terms, part=’snippet’, type=’video’,
order=’viewCount’, maxResults=50).execute()
Код возвращает объект JSON, который можно парсить для поиска соответствующей информации. Например, для нахождения даты публикации можно индексировать results
следующим образом:
publishedAt = results[‘items’][0][‘snippet’][‘publishedAt’]
Есть полезная серия видео, в которой подробно описывается процесс использования YouTube API.
Поиск ценных видео: задаём свою формулу
Теперь, когда я мог запрашивать соответствующую информацию, мне нужно было использовать полученные значения для ранжирования видео по их интересности для меня.
Это было непросто. В чём заключается интересность видео? В количестве просмотров? В количестве комментариев? В количестве подписчиков канала?
Я решил начать с общего количества просмотров как приближенной ценности видео на первой ступени. Теоретически, интересные или хорошо раскрывающие тему видео получают положительный отзыв аудитории, активнее продвигаются, а значит, имеют большее количество просмотров.
Однако есть аспекты, которые общее количество просмотров не учитывает:
Во-первых, если канал накопил большую аудиторию, то ему гораздо проще получить высокий уровень просмотров по сравнению с менее популярными каналами. Частично это может отражать больший опыт авторов, что ведёт к созданию более качественных видео, но я не хотел принижать в рейтинге потенциально высококачественные видео с мелких каналов. Видео с 100 000 просмотров на канале с 10 000 подписчиков вероятно лучше, чем видео с 100 000 просмотров на канале с 1 миллионом подписчиков.
Во-вторых, видео могут получать большое количество просмотров не по тем причинам, например, из-за кликбэйтных названий или превью, или из-за того, что вызывали споры. Лично мне меньше интересны подобные видео.
Мне нужно было как-то учесть эти метрики. Следующий параметр — это количество подписчиков.
Я протестировал рейтинги, основанные исключительно на соотношении просмотров к подписчикам (т.е. поделив просмотры на количество подписчиков).
# Function to calculate view-to-sub ratio
def view_to_sub_ratio(viewcount, num_subscribers):
if num_subscribers == 0:
return 0
else:
ratio = viewcount / num_subscribers
return ratio
При изучении результатов некоторые из них выглядели многообещающе. Однако я заметил проблему: для видео с очень малым количеством подписчиков оценка сильно возрастает и они поднимаются наверх.
Хотя верхнее видео потенциально выглядит интересными, второе и третье — это совсем не то, что я искал.
Я предпринял меры, чтобы устранить эти отрицательные граничные случаи:
- Задал минимальное количество просмотров — 5000
- Задал максимальное соотношение просмотров и подписчиков — 5
# Calculating ratio while removing edge cases (of low views or low subscribers)
def custom_score(viewcount, ratio, days_since_published):
ratio = min(ratio, 5)
score = (viewcount * ratio)
return score
Я поэкспериментировал с разными пороговыми значениями, и мне показалось, что именно эти достаточно хорошо отфильтровывают видео с малым количеством подписчиков и просмотров. Протестировав код на нескольких разных темах, я наконец начал получать довольно приличные результаты.
Однако я заметил ещё одну проблему: видео, опубликованные раньше, имели более высокую вероятность получить больше просмотров. У них просто было больше времени на накопление просмотров.
Я планировал запускать этот код раз в неделю, поэтому решил ограничить поиск видеороликами, опубликованными за последние 7 дней.
# Function to create string for search start date
def get_start_date_string(search_period_days):
"""Returns string for date at start of search period."""
search_start_date = datetime.today() – timedelta(search_period_days)
date_string = datetime(year=search_start_date.year,month=search_start_date.month,
day=search_start_date.day).strftime(‘%Y-%m-%dT%H:%M:%SZ’)
return date_string
# Creating date string and executing search
date_string = get_start_date_string(7)
results = youtube_api.search().list(q=search_terms, part=’snippet’,
type=’video’, order=’viewCount’, maxResults=50,
publishedAfter=date_string).execute()
Также я добавил в метрику ранжирования параметр «количество дней после публикации». Я решил делить предыдущую оценку на количество дней, чтобы окончательная метрика была пропорциональна времени после публикации.
# Adding days since published into custom score
def custom_score(viewcount, ratio, days_since_published):
if ratio > 5:
ratio = 5
score = (viewcount * ratio) / days_since_published
return score
Продолжив тестировать код, я выяснил, что он достаточно стабильно определяет отличные видео, которые мне хотелось бы посмотреть. Я поэкспериментировал с различными вариациями и весами компонентов моей формулы, но понял, что это неточная наука, поэтому остановился на следующей формуле, в которой, как мне показалось, есть баланс простоты с эффективностью:
Функция ценности
Тестируем новый инструмент
Сначала я протестировал его на запросе «medical school». Были получены следующие результаты:
Затем я зашёл на YouTube и вручную поискал видео, связанные с медициной и медицинскими образовательными учреждениями. Оказалось, что мой инструмент обнаружил все видео, которые мне было бы интересно посмотреть. В частности, мне понравилось видео доктора Кевина Джаббала (Kevin Jabbal).
Я протестировал ещё один поисковый запрос, «productivity», и снова был вполне доволен результатами:
Второе видео оказалось слегка неожиданным и не тем, что мне было нужно. Но я не смог придумать простого способа отсеивать эти видео, которые подбирались из-за другого значения поискового запроса.
Спустя несколько месяцев компания OpenAI выпустила очень интересную новую нейронную сеть под названием GPT-3. Я решил протестировать свой поисковик с поисковым запросом «GPT-3», и нашёл такое видео:
Это интересное видео автора всего с несколькими тысячами подписчиков.
Если бы я ввёл тот же запрос на YouTube.com, мне пришлось бы проскроллить все видео о GPT-3 всех крупных каналов, прежде чем найти это видео на 31-м месте.
Видео про GPT-3 на каналах с более крупными аудиториями
Поиск таких интересных видео со свежим взглядом намного проще выполнять при помощи написанного мной кода Video Finder.
За последние несколько месяцев я пробовал различные поисковые запросы по моим интересам, например, «artificial intelligence», «medical AI» и «Python programming». В пяти лучших видео, предложенных Video Finder, почти без сбоев всегда было хотя бы одно интересное видео.
Подготовка рабочего процесса
Я причесал код и загрузил его на GitHub.
Если описывать в общих чертах, мой код теперь работал следующим образом:
- Используем поисковые запросы, временной интервал и ключ API для извлечения информации с YouTube
- Парсим интересующие нас метрики видео
- Используем «функцию ценности» для ранжирования этих видео по прогнозируемой интересности
- Сохраняем соответствующую информацию видео в DataFrame
- Выводим в консоль подробности (в том числе ссылки) верхних пяти видео
Мне нужен был способ автоматического выполнения скрипта, и я решил использовать AWS Lambda (бессерверную платформу). Lambda позволяет писать код, который «спит», пока не включается (например, раз в неделю или на основании события).
В идеале процесс заключался бы в отправке при помощи Lambda автоматического письма со списком видео на мой ящик. Благодаря этому я мог бы выбирать видео из прошлого, которые бы хотел посмотреть на предстоящей неделе, и мне больше никогда не придётся заходить на главную страницу YouTube.
Однако этого не случилось.
Я впервые использовал Lambda и, как ни старался, у меня не получилось заставить одновременно работать все импортированные библиотеки. Для работы коду требуется клиент электронной почты boto3, OAuth для вызова API, Pandas для хранения результатов и множество других подзависимостей. Обычно установка этих пакетов тривиальна, но на Lambda появились дополнительные сложности. Во-первых, существуют ограничения памяти на загрузку, поэтому мне нужно было запаковать библиотеки в zip, а после загрузки распаковать их. Во-вторых, AWS Lambda использует специализированную сборку Linux, что усложняло импорт правильных перекрёстно совместимых библиотек. В-третьих, мой Mac вёл себя странно с этими виртуальными средами.
Потратив примерно 10-15 часов на изучение StackOverFlow, многократную загрузку разных кодовых баз и консультации с друзьями, я так и не смог заставить систему работать. Поэтому в конечном итоге, к своему разочарованию, был вынужден сдаться. (Если у вас есть идеи, то пишите!)
Поэтому я остановился на плане Б: вручную запускаю скрипт на моём локальном компьютере раз в неделю (после автоматического уведомления по электронной почте). Честно говоря, это не так уж страшно.
В заключение
В целом это оказался очень интересный проект. Я научился пользоваться YouTube API, познакомился с AWS Lambda и создал инструмент, который буду применять в дальнейшем.
Использование моего кода при выборе видео для просмотра, похоже, повышает мою продуктивность, если у меня хватает силы воли не нажимать на ссылки в конце видео. Возможно, я пропускаю некоторые интересные видео, но моя цель заключается не во всеобъемлющем отслеживании качественных видео, стоящих просмотра (я вообще не думаю, что это возможно). Вместо этого я хочу повысить планку качества видео, которые я смотрю.
Этот проект — одна из множества моих идей, связанных с автоматизированной обработкой информации. Я считаю, что у нас есть огромный потенциал в повышении продуктивности и экономии времени благодаря осмысленному минимализму пользования цифровой средой.
Потенциальные следующие шаги
В целом, проект ещё довольно сырой и с ним можно сделать намного больше.
- Метрика ранжирования видео довольно груба и её можно ещё совершенствовать. Логичным следующим шагом может быть учёт соотношения лайков/дизлайков.
- Также многое зависит от поисковых запросов. Если текста нет в названии или описании, то видео не будет выбрано. Можно исследовать возможность решения этой проблемы.
- Также можно создать интерфейс, в который пользователи вводят только поисковые запросы и временной интервал. Код при этом станет более удобным, а также позволит пользователям просматривать видео, даже не переходя на youtube.com.
- Пока код выполняется довольно медленно. Я не особо занимался оптимизацией его скорости, учитывая, что планирую запускать его только раз в неделю. Но в нём есть очевидные неэффективные фрагменты, которые можно улучшить.
На правах рекламы
Эпичные серверы — это VPS на Windows или Linux с мощными процессорами семейства AMD EPYC и очень быстрыми NVMe дисками Intel. Спешите заказать!
Автор: Mikhail