【问题标题】:python: get all youtube video urls of a channelpython:获取频道的所有 youtube 视频网址
【发布时间】:2013-03-08 21:07:07
【问题描述】:

我想获取特定频道的所有视频网址。我认为 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

【问题讨论】:

    标签: python youtube youtube-api


    【解决方案1】:

    在 youtube API 更改后,max k. 的答案不起作用。作为替代,下面的函数提供给定频道中的 youtube 视频列表。请注意,您需要API Key 才能使用它。

    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
    

    【讨论】:

    • 这是一个简单而准确的答案,因为我在 Python API 参考中找不到它。
    • @Stian 它给出了错误 HTTPError: HTTP Error 403: Forbidden
    • 对于 Python 3:import urllib.request,将 inp = urllib.urlopen(url) 更改为 inp = urllib.request.urlopen(url,timeout=1)
    • @smcs 它不起作用。 urllib.error.HTTPError:HTTP 错误 403:禁止
    • @rtt0012 你应该在codereview.stackexchange.com提出问题
    【解决方案2】:

    将最大结果从 1 增加到您想要的任意数量,但请注意,他们不建议在一次调用中获取太多结果,并且会将您限制为 50 (https://developers.google.com/youtube/2.0/developers_guide_protocol_api_query_parameters)。

    相反,您可以考虑以 25 个为一组来抓取数据,例如,通过更改 start-index 直到没有返回。

    编辑:这是我将如何做的代码

    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
    

    【讨论】:

    • 很好的答案,但最好使用“except SpecificError”之类的东西,而不是通用异常:如果 json 加载或响应解析有其他问题,这种代码将隐藏他们。
    • 好点子,如果发帖者决定使用它,那么做一些研究并找出具体错误绝对是个好主意
    • 如果你要删除:print len(video) 那么你会得到错误......所以我认为需要修复它。
    • @CatalinFestila 在我的情况下这不是真的。我可以删除每个打印件(包括 len(videos)),它会起作用。检查其他事项,然后重试。
    • 根据此回复youtube.com/devicesupport,我认为现在已弃用此功能
    【解决方案3】:

    根据此处和其他一些地方的代码,我编写了一个小脚本来执行此操作。我的脚本使用了 Youtube 的 API v3,并且没有达到 Google 为搜索设置的 500 个结果限制。

    代码可在 GitHub 上获得:https://github.com/dsebastien/youtubeChannelVideosFinder

    【讨论】:

    • 谢谢。结合pafy,您可以获取频道上的所有视频。
    • 这不适用于 PyCon 2015 频道,甚至 git 上提到的示例,它只是说找不到频道。我是不是做错了什么。
    • 我在使用它时遇到了很多错误。诚然,我的频道名称中似乎有一个空格,这在 cli 上造成了麻烦,但该工具没有取而代之的是 ID,但它搜索了 5 年并没有找到 vidz,我在频道上有 410 .
    • 仅供参考,我没有时间维护该项目,但如果有人感兴趣,请不要犹豫去修复它,我会很乐意合并任何改进 ;-)
    【解决方案4】:

    简答:

    这是一个可以帮助解决这个问题的库。

    pip install scrapetube

    import scrapetube
    
    videos = scrapetube.get_channel("UC9-y-6csu5WGm29I7JiwpnA")
    
    for video in videos:
        print(video['videoId'])
    

    长答案:

    由于缺乏任何其他解决方案,上述模块是我创建的。这是我尝试过的:

    1. 硒。它有效,但有三大缺点: 1. 它需要安装网络浏览器和驱动程序。 2. 对 CPU 和内存有很大的要求。 3. 无法处理大频道。
    2. 使用 youtube-dl。像这样:
    import youtube_dl
        youtube_dl_options = {
            'skip_download': True,
            'ignoreerrors': True
        }
        with youtube_dl.YoutubeDL(youtube_dl_options) as ydl:
            videos = ydl.extract_info(f'https://www.youtube.com/channel/{channel_id}/videos')
    

    这也适用于小型频道,但对于较大的频道,我会因为在这么短的时间内发出如此多的请求而被 youtube 阻止(因为 youtube-dl 会为频道中的每个视频下载更多信息)。

    所以我创建了库 scrapetube,它使用 Web API 来获取所有视频。

    【讨论】:

    • 非常好的解决方案,另外,如果有人要获取视频 url 代替 id,您可以使用 print("https://www.youtube.com/watch?v="+str(video['videoId'])) 代替 print(video['videoId'])
    【解决方案5】:

    独立的做事方式。没有api,没有速率限制。

    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
    

    上面的代码将仅废弃有限数量的视频网址,最多 60 个。如何抓取频道中存在的所有视频网址。能否请教一下。

    上面的代码 sn-p 将仅显示列出两次的所有视频的列表。并非频道中的所有视频网址。

    【讨论】:

      【解决方案6】:

      使用 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 多个视频的频道上遇到了问题。

      【讨论】:

        猜你喜欢
        • 2015-09-02
        • 2016-05-13
        • 2021-03-14
        • 2019-02-10
        • 1970-01-01
        • 2015-07-16
        • 2015-06-04
        • 2023-04-03
        • 2014-10-29
        相关资源
        最近更新 更多