Python: получить все YouTube видео-URL канала

Я хочу получить все URL-адреса видео определенного канала. Я думаю, что JSON с Python или Java будет хорошим выбором. Я могу получить новейшее видео с помощью следующего кода, но как я могу получить ВСЕ ссылки на видео (>500)?

import urllib, json
author = 'Youtube_Username'
inp = urllib.urlopen(r'http://gdata.youtube.com/feeds/api/videos?max-results=1&alt=json&orderby=published&author=' + author)
resp = json.load(inp)
inp.close()
first = resp['feed']['entry'][0]
print first['title'] # video title
print first['link'][0]['href'] #url

8 ответов

Решение

Увеличьте максимальные результаты с 1 до сколь угодно большого количества, но имейте в виду, что они не советуют брать слишком много за один вызов и ограничат вас до 50 ( https://developers.google.com/youtube/2.0/developers_guide_protocol_api_query_parameters).

Вместо этого вы могли бы рассмотреть возможность сбора данных в пакетах по 25, скажем, путем изменения стартового индекса до тех пор, пока они не вернутся.

РЕДАКТИРОВАТЬ: Вот код для того, как я бы это сделал

import urllib, json
author = 'Youtube_Username'

foundAll = False
ind = 1
videos = []
while not foundAll:
    inp = urllib.urlopen(r'http://gdata.youtube.com/feeds/api/videos?start-index={0}&max-results=50&alt=json&orderby=published&author={1}'.format( ind, author ) )
    try:
        resp = json.load(inp)
        inp.close()
        returnedVideos = resp['feed']['entry']
        for video in returnedVideos:
            videos.append( video ) 

        ind += 50
        print len( videos )
        if ( len( returnedVideos ) < 50 ):
            foundAll = True
    except:
        #catch the case where the number of videos in the channel is a multiple of 50
        print "error"
        foundAll = True

for video in videos:
    print video['title'] # video title
    print video['link'][0]['href'] #url

Вот библиотека, которая может в этом помочь.

pip install list_youtube_channel

      import list_youtube_channel

videos = list_youtube_channel.get_channel("UC9-y-6csu5WGm29I7JiwpnA")

for video in videos:
    print(video['videoId'])

После изменения API youtube ответ max k. Не работает. В качестве замены приведенная ниже функция предоставляет список видео на YouTube для данного канала. Обратите внимание, что для работы вам необходим ключ API.

import urllib
import json

def get_all_video_in_channel(channel_id):
    api_key = YOUR API KEY

    base_video_url = 'https://www.youtube.com/watch?v='
    base_search_url = 'https://www.googleapis.com/youtube/v3/search?'

    first_url = base_search_url+'key={}&channelId={}&part=snippet,id&order=date&maxResults=25'.format(api_key, channel_id)

    video_links = []
    url = first_url
    while True:
        inp = urllib.urlopen(url)
        resp = json.load(inp)

        for i in resp['items']:
            if i['id']['kind'] == "youtube#video":
                video_links.append(base_video_url + i['id']['videoId'])

        try:
            next_page_token = resp['nextPageToken']
            url = first_url + '&pageToken={}'.format(next_page_token)
        except:
            break
    return video_links

Основываясь на коде, найденном здесь и в некоторых других местах, я написал небольшой скрипт, который делает это. Мой сценарий использует API YouTube версии 3 и не соответствует пределу в 500 результатов, который Google установил для поисковых запросов.

Код доступен на GitHub: https://github.com/dsebastien/youtubeChannelVideosFinder

Независимый способ делать вещи.

import requests
username = "marquesbrownlee"
url = "https://www.youtube.com/user/username/videos"
page = requests.get(url).content
data = str(page).split(' ')
item = 'href="/watch?'
vids = [line.replace('href="', 'youtube.com') for line in data if item in line] # list of all videos listed twice
print(vids[0]) # index the latest video

Я сделал некоторые дополнительные улучшения, чтобы иметь возможность добавить URL-адрес канала в консоль, распечатать результат на экране, а также во внешний файл с именем «_list.txt».

      import scrapetube
import sys

path = '_list.txt'

print('**********************\n')
print("The result will be saved in '_list.txt' file.")
print("Enter Channel ID:")

# Prints the output in the console and into the '_list.txt' file.
class Logger:
 
    def __init__(self, filename):
        self.console = sys.stdout
        self.file = open(filename, 'w')
 
    def write(self, message):
        self.console.write(message)
        self.file.write(message)
 
    def flush(self):
        self.console.flush()
        self.file.flush()

sys.stdout = Logger(path)

# Strip the: "https://www.youtube.com/channel/"
channel_id_input = input()
channel_id = channel_id_input.strip("https://www.youtube.com/channel/")

videos = scrapetube.get_channel(channel_id)

for video in videos:
    print("https://www.youtube.com/watch?v="+str(video['videoId']))
#    print(video['videoId'])

Использование драйвера Selenium Chrome:

from selenium import webdriver
from webdriver_manager.chrome import ChromeDriverManager
import time

driverPath = ChromeDriverManager().install()

driver = webdriver.Chrome(driverPath)

url = 'https://www.youtube.com/howitshouldhaveended/videos'

driver.get(url)

height = driver.execute_script("return document.documentElement.scrollHeight")
previousHeight = -1

while previousHeight < height:
    previousHeight = height
    driver.execute_script(f'window.scrollTo(0,{height + 10000})')
    time.sleep(1)
    height = driver.execute_script("return document.documentElement.scrollHeight")

vidElements = driver.find_elements_by_id('thumbnail')
vid_urls = []
for v in vidElements:
    vid_urls.append(v.get_attribute('href'))

Этот код работал несколько раз, когда я его пробовал; однако вам может потребоваться настроить время сна или добавить способ распознавания, когда браузер все еще загружает дополнительную информацию. У меня легко получилось получить канал с более чем 300 видео, но у меня возникла проблема с тем, на котором было более 7000 видео, из-за того, что время, необходимое для загрузки новых видео в браузер, становилось непоследовательным.

Я изменил сценарий, первоначально опубликованный dermasmid, чтобы он соответствовал моим потребностям. Вот результат:

      import scrapetube
import sys

path = '_list.txt'
sys.stdout = open(path, 'w')

videos = scrapetube.get_channel("UC9-y-6csu5WGm29I7JiwpnA")

for video in videos:
    print("https://www.youtube.com/watch?v="+str(video['videoId']))
#    print(video['videoId'])

По сути, он сохраняет все URL-адреса из списка воспроизведения в файл «_list.txt». Я использую этот файл «_list.txt» для загрузки всех видео с помощью yt-dlp.exe. Все загруженные файлы имеют расширение .mp4.

Теперь мне нужно создать еще один файл "_playlist.txt", который содержит все ИМЕНА ФАЙЛОВ, соответствующие каждому URL-адресу из "_List.txt".

Например, для: «https://www.youtube.com/watch?v=yG1m7oGZC48», чтобы «Apple M1 Ultra & NUMA — Computerphile.mp4» выводился в «_playlist.txt».

Другие вопросы по тегам