python

Запоминаем просмотренные видео на youtube

  • среда, 22 апреля 2015 г. в 02:10:49
http://habrahabr.ru/post/255549/



Интро


Столкнулся с тем, что youtube.com «забывает» видео, которые я просмотрел.
Приходится смотреть много образовательных каналов, а потом вспоминать, видел я это или нет.
Посмотрел какую-нибудь лекцию и через несколько дней (месяцев, лет) статус "просмотрено" пропадает.
Или, наоборот, посмотришь 2 минуты какой-нибудь лекции, ляжешь спать, а на утро лекция имеет статус «просмотрено».

Вот и решил взять под контроль информацию о просмотрах в свои руки.
И хранить эту информацию вне зависимости от ютюба.
Если у кого-нибудь есть нужда в такого рода запоминании просмотров, то добро пожаловать под кат.

Скриншоты


Иногда скриншоты лучше объясняют, чем сама статья.
Поэтому привожу их в первую очередь:


Можно добавить каналы, которые вам интересны.





Реализация на любом языке веб-программирования


Итак, пишем свой youtube с возможностью запоминания просмотров и с прекрасными лекторшами.
«Наш ютюб» будет получать информацию от google API и будет своего рода прослойкой между вами и ютюбом.
И будет хранить информацию о просмотрах в нашей базе данных.

Я написал это на python и фреймворке flask, получилось 70 строк, ссылка на гитхаб внизу статьи.
Но так как это можно воссоздать и на php, и на perl и на других языках для веб, то сначала общие принципы…

Работа с google API


Получить ключ google API к youtube. Можно здесь.

Информация о канале
Для создания сайта нам понадобится получать информацию о канале.
Возьмем для примера вот такую ссылку:
www.youtube.com/channel/UC640y4UvDAlya_WOj5U4pfA
UC640y4UvDAlya_WOj5U4pfA — это ID канала.
Обращаемся к API:

curl 'https://www.googleapis.com/youtube/v3/channels?part=snippet&id=UC640y4UvDAlya_WOj5U4pfA&key=ВАШ_КЛЮЧ_API'

И получаем вот такой ответ в формате JSON
{
 "kind": "youtube#channelListResponse",
 "etag": "\"kYnGHzMaBhcGeLrcKRx6PAIUosY/YqjVAeQ4_JORc2ijoBKla3hrDXE\"",
 "pageInfo": {
  "totalResults": 1,
  "resultsPerPage": 1
 },
 "items": [
  {
   "kind": "youtube#channel",
   "etag": "\"kYnGHzMaBhcGeLrcKRx6PAIUosY/OE6leaeClJlkthEEiPP5KVJQZPQ\"",
   "id": "UC640y4UvDAlya_WOj5U4pfA",
   "snippet": {
    "title": "nptelhrd",
    "description": "Your favorite courses available for certification! study, write an exam and get a certificate from the IITs! Check http://nptel.ac.in/noc\n\nThis channel provides technical lectures from seven Indian Institutes of Technology (IITs) and Indian Institute of Science (IISc) Bangalore.\n\nPlease visit the NPTEL Channel List below to view the complete list of courses. (24 Channels)",
    "publishedAt": "2007-11-28T04:54:13.000Z",
    "thumbnails": {
     "default": {
      "url": "https://yt3.ggpht.com/-VO_A5Tys4WY/AAAAAAAAAAI/AAAAAAAAAAA/mBvvbUvh0A8/s88-c-k-no/photo.jpg"
     },
     "medium": {
      "url": "https://yt3.ggpht.com/-VO_A5Tys4WY/AAAAAAAAAAI/AAAAAAAAAAA/mBvvbUvh0A8/s240-c-k-no/photo.jpg"
     },
     "high": {
      "url": "https://yt3.ggpht.com/-VO_A5Tys4WY/AAAAAAAAAAI/AAAAAAAAAAA/mBvvbUvh0A8/s240-c-k-no/photo.jpg"
     }
    },
    "localized": {
     "title": "nptelhrd",
     "description": "Your favorite courses available for certification! study, write an exam and get a certificate from the IITs! Check http://nptel.ac.in/noc\n\nThis channel provides technical lectures from seven Indian Institutes of Technology (IITs) and Indian Institute of Science (IISc) Bangalore.\n\nPlease visit the NPTEL Channel List below to view the complete list of courses. (24 Channels)"
    }
   }
  }
 ]
}



Отсюда можно дернуть поле 'title' и использовать как название канала.

Получаем список видео с канала
curl 'https://www.googleapis.com/youtube/v3/search?part=snippet&channelId=UCEBb1b_L6zDS3xTUrIALZOw&order=date&key=ВАШ_КЛЮЧ_API'


И получаем вот такой ответ в формате JSON
{
 "kind": "youtube#searchListResponse",
 "etag": "\"kYnGHzMaBhcGeLrcKRx6PAIUosY/vGlosUUKRoHE50sX08btNSJuUT0\"",
 "nextPageToken": "CAUQAA",
 "pageInfo": {
  "totalResults": 3493,
  "resultsPerPage": 5
 },
 "items": [
  {
   "kind": "youtube#searchResult",
   "etag": "\"kYnGHzMaBhcGeLrcKRx6PAIUosY/f-Aj24y6ay5s_ofPTa82fwx3hP0\"",
   "id": {
    "kind": "youtube#video",
    "videoId": "NtMOab_nhs0"
   },
   "snippet": {
    "publishedAt": "2015-04-02T00:35:45.000Z",
    "channelId": "UCEBb1b_L6zDS3xTUrIALZOw",
    "title": "Octave/MATLAB® for Beginners, Part 2: Fitting Data and Plotting",
    "description": "MIT 22.15 Essential Numerical Methods, Fall 2014 View the complete course: http://ocw.mit.edu/22-15F14 Instructor: Ian Hutchinson Plotting the line that results ...",
    "thumbnails": {
     "default": {
      "url": "https://i.ytimg.com/vi/NtMOab_nhs0/default.jpg"
     },
     "medium": {
      "url": "https://i.ytimg.com/vi/NtMOab_nhs0/mqdefault.jpg"
     },
     "high": {
      "url": "https://i.ytimg.com/vi/NtMOab_nhs0/hqdefault.jpg"
     }
    },
    "channelTitle": "MIT",
    "liveBroadcastContent": "none"
   }
  },
  {
   "kind": "youtube#searchResult",
   "etag": "\"kYnGHzMaBhcGeLrcKRx6PAIUosY/qLJGwF303RMmdl03IbivB2VkIQ4\"",
   "id": {
    "kind": "youtube#video",
    "videoId": "WUxImdA7k8E"
   },
   "snippet": {
    "publishedAt": "2015-04-02T00:35:45.000Z",
    "channelId": "UCEBb1b_L6zDS3xTUrIALZOw",
    "title": "Octave/MATLAB® for Beginners, Part 3: Cleaning Up & Saving Plots",
    "description": "MIT 22.15 Essential Numerical Methods, Fall 2014 View the complete course: http://ocw.mit.edu/22-15F14 Instructor: Ian Hutchinson Cleaning up and saving ...",
    "thumbnails": {
     "default": {
      "url": "https://i.ytimg.com/vi/WUxImdA7k8E/default.jpg"
     },
     "medium": {
      "url": "https://i.ytimg.com/vi/WUxImdA7k8E/mqdefault.jpg"
     },
     "high": {
      "url": "https://i.ytimg.com/vi/WUxImdA7k8E/hqdefault.jpg"
     }
    },
    "channelTitle": "MIT",
    "liveBroadcastContent": "none"
   }
  },
  {
   "kind": "youtube#searchResult",
   "etag": "\"kYnGHzMaBhcGeLrcKRx6PAIUosY/mKjnuWcbJIZE_fKn12kg7B-lrN0\"",
   "id": {
    "kind": "youtube#video",
    "videoId": "LhPZwdhutgU"
   },
   "snippet": {
    "publishedAt": "2015-04-02T00:35:45.000Z",
    "channelId": "UCEBb1b_L6zDS3xTUrIALZOw",
    "title": "Octave/MATLAB® for Beginners, Part 1: Starting from Scratch",
    "description": "MIT 22.15 Essential Numerical Methods, Fall 2014 View the complete course: http://ocw.mit.edu/22-15F14 Instructor: Ian Hutchinson Create adjacent windows ...",
    "thumbnails": {
     "default": {
      "url": "https://i.ytimg.com/vi/LhPZwdhutgU/default.jpg"
     },
     "medium": {
      "url": "https://i.ytimg.com/vi/LhPZwdhutgU/mqdefault.jpg"
     },
     "high": {
      "url": "https://i.ytimg.com/vi/LhPZwdhutgU/hqdefault.jpg"
     }
    },
    "channelTitle": "MIT",
    "liveBroadcastContent": "none"
   }
  },
  {
   "kind": "youtube#searchResult",
   "etag": "\"kYnGHzMaBhcGeLrcKRx6PAIUosY/EteK6EKK5CG4IAAX3JjzWUD0oAQ\"",
   "id": {
    "kind": "youtube#playlist",
    "playlistId": "PLUl4u3cNGP63_OOz8w5qDEoqErZ8Hj-fc"
   },
   "snippet": {
    "publishedAt": "2015-04-02T00:34:03.000Z",
    "channelId": "UCEBb1b_L6zDS3xTUrIALZOw",
    "title": "MIT 22.15 Essential Numerical Methods, Fall 2014",
    "description": "View the complete course: http://ocw.mit.edu/22-15F14 Instructor: Ian Hutchinson Three short tutorial videos which demonstrate basic operation of Octave software, used in this graduate-level...",
    "thumbnails": {
     "default": {
      "url": "https://i.ytimg.com/vi/LhPZwdhutgU/default.jpg"
     },
     "medium": {
      "url": "https://i.ytimg.com/vi/LhPZwdhutgU/mqdefault.jpg"
     },
     "high": {
      "url": "https://i.ytimg.com/vi/LhPZwdhutgU/hqdefault.jpg"
     }
    },
    "channelTitle": "MIT",
    "liveBroadcastContent": "none"
   }
  },
  {
   "kind": "youtube#searchResult",
   "etag": "\"kYnGHzMaBhcGeLrcKRx6PAIUosY/jI4Bwr7emgpt45cnFetFPewI7qU\"",
   "id": {
    "kind": "youtube#playlist",
    "playlistId": "PLUl4u3cNGP62FPGcyFJkzhqq9c5cHCK32"
   },
   "snippet": {
    "publishedAt": "2015-03-23T21:38:55.000Z",
    "channelId": "UCEBb1b_L6zDS3xTUrIALZOw",
    "title": "MIT 8.421 Atomic and Optical Physics I, Spring 2014",
    "description": "MIT 8.421 Atomic and Optical Physics I, Spring 2014 View the complete course: http://ocw.mit.edu/8-421S14 Instructor: Wolfgang Ketterle This is the first of a ...",
    "thumbnails": {
     "default": {
      "url": "https://i.ytimg.com/vi/iwQ49oG-DO8/default.jpg"
     },
     "medium": {
      "url": "https://i.ytimg.com/vi/iwQ49oG-DO8/mqdefault.jpg"
     },
     "high": {
      "url": "https://i.ytimg.com/vi/iwQ49oG-DO8/hqdefault.jpg"
     }
    },
    "channelTitle": "MIT",
    "liveBroadcastContent": "none"
   }
  }
 ]
}


По умолчанию он будет выводить за один раз 5 последних видео с канала.
Чтобы это изменить, можно добавить параметр &maxResults=10, например.
Для навигации по страницам канала в JSON выдаются следующие значения:
«nextPageToken» и «prevPageToken».
Если нужно перейти на следующую или предыдущую страницу, то вводим дополнительный параметр &pageToken=
и подставляем сюда значение «nextPageToken» или «prevPageToken».

Информация об отдельно взятом видео
Вообще я этот запрос не использовал в своем сайте, но может пригодиться.
Поэтому привожу его:
curl 'https://ww.googleapis.com/youtube/v3/videos?part=snippet&id=EhNWzcUwqGbI&key=ВАШ_КЛЮЧ_API'


И получаем вот такой ответ в формате JSON
{
 "kind": "youtube#videoListResponse",
 "etag": "\"IHLB7Mi__JPvvG2zLQWAg8l36UU/2kAxpYyny-CEVVbQ2cOjO-XSscQ\"",
 "pageInfo": {
  "totalResults": 1,
  "resultsPerPage": 1
 },
 "items": [
  {
   "kind": "youtube#video",
   "etag": "\"IHLB7Mi__JPvvG2zLQWAg8l36UU/vAIAewyN9KKpNPERU4b4tOjuPL4\"",
   "id": "EhNWzcUqGbI",
   "snippet": {
    "publishedAt": "2013-03-16T06:58:52.000Z",
    "channelId": "UCuLLf8HBxpa-RV1sf9CRmDg",
    "title": "50 MPH 52v Electric Mountain Bike",
    "description": "http://voltbicycles.com This is our Alite 1000 Electric Mountain bike powered by a black lighting brushless rear hub electric motor with a 52v battery system. This electric bike will do around 50 MPH and will run 30+ miles on a single charge. \n\nGOING GREEN DOESN'T HAVE TO BE BORING",
    "thumbnails": {
     "default": {
      "url": "https://i.ytimg.com/vi/EhNWzcUqGbI/default.jpg",
      "width": 120,
      "height": 90
     },
     "medium": {
      "url": "https://i.ytimg.com/vi/EhNWzcUqGbI/mqdefault.jpg",
      "width": 320,
      "height": 180
     },
     "high": {
      "url": "https://i.ytimg.com/vi/EhNWzcUqGbI/hqdefault.jpg",
      "width": 480,
      "height": 360
     },
     "standard": {
      "url": "https://i.ytimg.com/vi/EhNWzcUqGbI/sddefault.jpg",
      "width": 640,
      "height": 480
     },
     "maxres": {
      "url": "https://i.ytimg.com/vi/EhNWzcUqGbI/maxresdefault.jpg",
      "width": 1280,
      "height": 720
     }
    },
    "channelTitle": "bradscottphotography",
    "categoryId": "28",
    "liveBroadcastContent": "none",
    "localized": {
     "title": "50 MPH 52v Electric Mountain Bike",
     "description": "http://voltbicycles.com This is our Alite 1000 Electric Mountain bike powered by a black lighting brushless rear hub electric motor with a 52v battery system. This electric bike will do around 50 MPH and will run 30+ miles on a single charge. \n\nGOING GREEN DOESN'T HAVE TO BE BORING"
    }
   }
  }
 ]
}



Как быть с текущей историей просмотров?


Текущая история просмотров хранится здесь:
www.youtube.com/feed/history
Нажимаете до победного конца на кнопку «Еще», пока не загрузится вся история, которая там хранится.
Далее сохраняем в html файл.
Я набросал небольшой парсер на perl, который выдергивает ID всех видео из сохраненного файла с историей.
use strict;
use warnings;
use utf8;
use Mojo::DOM;
use File::Slurp;
use feature 'say';

my $body = read_file( 'youtube_history.html', binmode => ':utf8' );
my $dom = Mojo::DOM->new($body);

for my $e ( $dom->find('div.yt-uix-tile')->each ) {
    say  $e->{'data-context-item-id'};

}


На выходе получаем список всех ID на ютюбе, которые были в youtube_history.html.
Можно загрузить его в нашу локальную базу и таким образом отметить видео, как просмотренное.

Немного о реализации на фреймворке flask


Ссылка на github:
github.com/Alexmod/memtube
На хабре была целая серия статей о flask, так что подробно не буду останавливаться.
Но если хотите запустить данный файл, то ставьте виртуальное окружение, устанавливайте все модули, которые нужны для старта,
и запускайте командой:
python main.py 

Если все ок, то увидете следующее:
 * Running on http://0.0.0.0:5000/
 * Restarting with reloader

Локальная версия youtube.com готова.
После первого запуска будет создан файл video.db в этой же директории, в котором и будет храниться информация о просмотрах.