74

我正在使用 youtube v3 API 检索播放列表的视频并获得 50 个项目,而此链接没有任何问题:-

https://www.googleapis.com/youtube/v3/playlistItems?part=snippet&maxResults=50&playlistId=PLB03EA9545DD188C3&key=MY_API_KEY

但是视频数是 100,而我只有 50 个。我怎样才能获得接下来的 50 个项目?我尝试了start-index但它不适用于 v3 API。任何帮助表示赞赏。

4

9 回答 9

61

YouTube Data API v3 结果是分页的。因此,您需要为其他人获取下一页结果。

基本上在响应中你有nextPageToken

要获得剩余的结果,请执行相同的调用,但将pageToken设置为您收到的令牌。

于 2013-09-14T20:18:39.077 回答
34

有三个令牌

  1. 页面令牌
  2. 下一页令牌
  3. 上一页PageToken

你也可以使用设置最大页面大小

maxResults=50 {允许的值 1 到 50 }

如果你在第 1 页,你不会得到prevPageToken

但你得到nextPageToken

将此令牌传递给下一个请求

pageToken = {nextPageToken 从上次请求中获取}

这样你就可以导航到下一页自己试试

已编辑

好的,对于其他场景

如果您在首页,那么

  1. pageToken = '一些值'
  2. nextPageToken = '一些值'
  3. prevPageToken = null

如果您既不在第一页也不在最后一页,那么

  1. pageToken = '一些值'
  2. nextPageToken = '一些值'
  3. prevPageToken = '一些值'

@Manoj:你可以在下面找到你的答案

如果你在最后一页

  1. pageToken = '一些值'
  2. nextPageToken = null
  3. prevPageToken = '一些价值'

甚至该字段也可能不存在。

于 2013-09-15T07:41:31.297 回答
22

这是一个使用 Python Youtube Client Lib 在 python 中制作的小例子这也从 youtube API 示例中借用了样板设置

""" Pull All Youtube Videos from a Playlist """

from apiclient.discovery import build
from apiclient.errors import HttpError
from oauth2client.tools import argparser


DEVELOPER_KEY = "YOURKEY HERE"
YOUTUBE_API_SERVICE_NAME = "youtube"
YOUTUBE_API_VERSION = "v3"

def fetch_all_youtube_videos(playlistId):
    """
    Fetches a playlist of videos from youtube
    We splice the results together in no particular order

    Parameters:
        parm1 - (string) playlistId
    Returns:
        playListItem Dict
    """
    youtube = build(YOUTUBE_API_SERVICE_NAME,
                    YOUTUBE_API_VERSION,
                    developerKey=DEVELOPER_KEY)
    res = youtube.playlistItems().list(
    part="snippet",
    playlistId=playlistId,
    maxResults="50"
    ).execute()

    nextPageToken = res.get('nextPageToken')
    while ('nextPageToken' in res):
        nextPage = youtube.playlistItems().list(
        part="snippet",
        playlistId=playlistId,
        maxResults="50",
        pageToken=nextPageToken
        ).execute()
        res['items'] = res['items'] + nextPage['items']

        if 'nextPageToken' not in nextPage:
            res.pop('nextPageToken', None)
        else:
            nextPageToken = nextPage['nextPageToken']

    return res

if __name__ == '__main__':
  # comedy central playlist, has 332 video
  # https://www.youtube.com/watch?v=tJDLdxYKh3k&list=PLD7nPL1U-R5rDpeH95XsK0qwJHLTS3tNT
  videos = fetch_all_youtube_videos("PLD7nPL1U-R5rDpeH95XsK0qwJHLTS3tNT")

视频将是连接到第一个列表的所有视频的列表。由于分页数为 50,它将继续获取直到拥有所有视频。类似的方法可以在其他语言中采用。

在列表中将有所有单独的视频元数据和顺序

于 2015-08-03T19:49:50.787 回答
9

在 youtube 发送给我们的 JSON 数据中,data.pageInfo.totalResults 只是原始的视频总数。几个月或几年后,这个数字可能会因为视频删除、禁止而减少……实际上 youtube 只为我们提供当前可播放的视频。因此,我们需要更改代码以获得更好的代码。
我们不应该使用 if(sum == data.pageInfo.toTalResults) 作为停止条件。相反,让我们使用标准 if(typeof nextPageToken == 'undefined')。
在当前总数小于原始总数的情况下。如果我们使用旧编码,那么最后一个函数调用是使用未定义的 nextPageToken 进行的。这导致 Youtube 再次错误地给了我们第一个 JSON 页面。在结果中,我们有一些重复的视频。
请尝试我的新编码(看起来像 user3053204 先生给出的编码)

/* new coding. Please replace and use your api3 key */

function start(){
    count = 0; 
    $('#area1').val('');
    getVids();
}
function getVids(PageToken){
pid = $('#searchtext1').val();
$.get(
    "https://www.googleapis.com/youtube/v3/playlistItems",{
    part : 'snippet', 
    maxResults : 50,
    playlistId : pid,
    pageToken : PageToken,
    key: 'AIz....................................zm4'
    },
    function(data){
          myPlan(data);
    }        
    );  
}
count = 0;
str = '';

 function myPlan(data){
  nextPageToken=data.nextPageToken;
  pageLen = data.items.length;
  count += parseInt(pageLen);
  for(i=0; i<pageLen; i++){
           str += '"' + data.items[i].snippet.resourceId.videoId + '", ';
  }
   if(typeof nextPageToken == 'undefined'){
          total = data.pageInfo.totalResults;
          $('#all').html(count + '/' + total + ' videos');
          ind = str.lastIndexOf(',');
          str1 = str.substring(0, ind);
          $('#area1').val('arr = [' + str1 + '];\n');
          return;      
      }else{
          getVids(nextPageToken);
      }
 }

 <input type="text"  value="PLTI6yRvQqlYq9KoU-NHu43uDmKON7Fsjv" 
  id="searchtext1" size="75">&nbsp;
 <button onclick="start()">Get Items</button>
 <br><br>
 IDs for test: <br>
 <br>
 Ricky King playlist (92/103 videos):<br>
 PLTI6yRvQqlYq9KoU-NHu43uDmKON7Fsjv<br>
 Franck Pourcel playlist (425/425 videos):<br>
 PLMGmDo5xNOgU7gerHMwEk6SmD_vbPyLe9<br>
 Lobo playlist (25/41vids):<br>
 PLFE095732AC64AD06
 <br><br>         
 TOTAL:&nbsp;<span id="all"></span><br>
 <textarea id="area1" style="width:600px;height:500px;;font-size:12pt"></textarea>

/* old coding - to be cleared */

sum = 0;
sumN = 1;
var nextPageToken;

function getVids(PageToken){
    pid = $('#searchtext1').val();
    $.get(
        "https://www.googleapis.com/youtube/v3/playlistItems",{
        part : 'snippet', 
        maxResults : 50,
        playlistId : pid,
        pageToken : PageToken,
        key: 'YOUR API3 KEY'
        },
        function(data){
              myPlan(data);
        }        
    );  
 }

  function myPlan(data){
      total = data.pageInfo.totalResults;
      nextPageToken=data.nextPageToken;
      for(i=0;i<data.items.length;i++){
          document.getElementById('area1').value +=  
          sumN + '-' + data.items[i].snippet.title+'\n'+
          data.items[i].snippet.resourceId.videoId +'\n\n';
          sum++ ; sumN++;
          if(sum == (total-1) ){              
              sum = 0;  
              return;      
          }
      }  
      if(sum <(total-1)){
          getVids(nextPageToken);
      }    
 }
 
 function init(){
    $('#area1').val('');
 }
<!- - old coding - to be cleared - ->
<meta http-equiv="content-type" content="text/html; charset=utf-8">
<script type="text/javascript" src="http://code.jquery.com/jquery-latest.js"></script>
  
  <body onload="$('#area1').val('')">
    
  <input type="text"  value="PLTI6yRvQqlYq9KoU-NHu43uDmKON7Fsjv" 
  id="searchtext1" size="75">&nbsp;
  <button onclick="getVids()">Get Items</button>
  <br><br>
  IDs for test: <br>PLTI6yRvQqlYq9KoU-NHu43uDmKON7Fsjv<br>
  PL32C69B40337EF920
  <br><br>         
  <textarea id="area1" style="width:600px;height:500px">
  </textarea>

于 2015-11-24T20:32:54.037 回答
1

获取所有视频的最简单方法,

DEVELOPER_KEY = "REPLACE_ME" YOUTUBE_API_SERVICE_NAME = "youtube" YOUTUBE_API_VERSION = "v3"

youtube = build("youtube", "v3", developerKey=api_key)
def get_videos_from_playlist(youtube, items, playlistID):
    response = items.list(part="snippet", playlistId=playlistID)
    while response:
        playlistitems_list_response = response.execute()

        for playlist_item in playlistitems_list_response["items"]:
            # title = playlist_item["snippet"]["title"]
            video_id = playlist_item["snippet"]["resourceId"]["videoId"]
            yield video_id

        response = youtube.playlistItems().list_next(
        response, playlistitems_list_response)

传递播放列表 ID,

items = youtube.playlistItems()
playlist = get_videos_from_playlist(youtube, items, 'PLoROMvodv4rOhcuXMZkNm7j3fVwBBY42z')

然后解析列表:

for videoID in playlist:
    print(videoID)

此外,您可以使用页面来抓取多个页面,例如:

nextPageToken = res.get('nextPageToken')
    while ('nextPageToken' in res):
        nextPage = youtube.playlistItems().list(
        part="snippet",
        playlistId=playlistId,
        maxResults="50",
        pageToken=nextPageToken
        ).execute()
        res['items'] = res['items'] + nextPage['items']

        if 'nextPageToken' not in nextPage:
            res.pop('nextPageToken', None)
        else:
            nextPageToken = nextPage['nextPageToken']
于 2019-12-03T14:18:53.110 回答
0

另一种解决方案,使用递归:

$.fn.loadYoutubeResource = function(resource_request, resource_type, resource_id, resource_container, pageToken = null, callback = null){
    $.ajax({
            url: "https://www.googleapis.com/youtube/v3/" + resource_request,
            type: 'get',
            dataType: 'json',
            data: {
                    part : 'snippet', 
                    [resource_type]: resource_id,
                    maxResults : 50,
                    pageToken: pageToken,
                    key: '< API Key >', 
                  },
            success:    function(data) {
                                console.log("New resource " + resource_type + " loaded:");
                                console.log(data);                                          
                                for(var index = 0; index < data.items.length; index++){                                         
                                    var url = data.items[index]['snippet'].thumbnails.default.url;
                                    var ytb_id = data.items[index]['id'];   
                                    jQuery('#' + resource_container).append('<img class="tube_thumbs" src="' + url + '" id="' + ytb_id 
                                                                        + '" title="' + data.items[index]['snippet']['title'] + '" >');
                                    }
                                if ( data.nextPageToken == null)
                                    return callback();
                                $.fn.loadYoutubeResource(resource_request, resource_type, resource_id, resource_container, data.nextPageToken, callback);                   
                        }
            });     
        }        

然后按如下方式调用它:

jQuery('body').append('<div id="ytb_container"></div>');

$.fn.loadYoutubeResource('playlistItems', 'playlistId', 'PLmwK57OwOvYVdedKc_vPPfbcsey_R0K8r', 'ytb_container', null, function(){ <callback code>});
于 2016-12-05T03:36:30.020 回答
0

这是我的递归函数,也许可以帮助某人:

首先,我为第一次通话创建了一个按钮:

<button id="aux" class="btn btn-danger">Click Me</button>    

然后在脚本部分:

   $(document).ready(function () {

        function getVideos(t) {
            var url = "https://www.googleapis.com/youtube/v3/search?part=snippet&key=YourAPIKey&channelId=YourChannelID&maxResults=50";
            if (t != undefined) {
                url = url + "&pageToken=" + t
            }
            $.ajax({
                type: 'GET',
                url: url,
                dataType: 'json',
                success: function (html) {
                    console.log(html.items);
                    if (html.nextPageToken != undefined) {
                        getVideos(html.nextPageToken);
                    }
                }
            });
        };

        //initial call
        $("#aux").click(function () {
            getVideos();
        });
 });

问候

于 2018-08-03T11:17:25.103 回答
0

另一种方法(不需要知道请求格式并拥有api密钥):只需使用youtube播放列表html文件中的json并使用JSON.parse方法
不幸的是,这种方法不能提供超过200个视频。在 json 中,我看到了一些关键代码,可能是为了继续,但不能使用它们。
要获取 html 源代码,我们可以使用 jquery $.ajax 方法。

<meta charset = utf-8>
<body>
<div id="help" style="width:90%">
1- Open youtube.com and search for playlist   (http://www.youtube.com/....&list=...)<br>
For example: click <a href="http://www.youtube.com/watch?v=sMyj9e2qOc0&list=PL33196EF7664597D5">paul mauriat playlist</a><br>
You will see in the adress bar: http://www.youtube.com/watch?v=sMyj9e2qOc0&list=PL33196EF7664597D5 <br>
Select all and copy this url.<br>
2- Open any online html source code  viewer. For example<br>
<a href="https://www.duplichecker.com/page-snooper.php">
https://www.duplichecker.com/page-snooper.php</a><br>
Paste the url, click "Enter", wait several seconds, scroll down, click   "Copy"<br>
3- Return to this page. Paste the code to the below input smal textarea, wait several seconds, click "GET VIDEO IDS".<br>
4- Click the button TEST JAVASCRIPT.
</div><br>
<textarea id = "input">
</textarea><br>
<button onclick="extract()">GET VIDEOS IDS</button><br>
Total:&nbsp;<span id='len'></span>
<br><button onclick="test()">TEST JAVASCRIPT</button><br>
COPY THIS TO CREATE A JAVASCRIPT FILE<br>
<textarea id="area2" style="width:90%;height:400px;font-size:14pt">
</textarea><br>

<script> 
function extract(){
str = document.getElementById('input').value;
aa = str.indexOf('{"responseContext');
bb = str.indexOf('{"related', aa);
jsn = str.substring(aa, bb + 24);
obje = JSON.parse(jsn);
alert('Click OK to continue');
make();
}
glStr = '';
function make(){
len = obje.contents.singleColumnWatchNextResults.playlist.playlist.contents.length;
ss = '';
for(i=0; i < len; i++){
try{
   ti = obje.contents.singleColumnWatchNextResults.playlist.playlist.contents[i].playlistPanelVideoRenderer.title.runs[0].text;
   ti1 = ti.replace(/"/g,'\\"');
   ide = obje.contents.singleColumnWatchNextResults.playlist.playlist.contents[i].playlistPanelVideoRenderer.navigationEndpoint.watchEndpoint.videoId;
    }catch(e){
                ide = obje.contents.singleColumnWatchNextResults.playlist.playlist.contents[i].playlistPanelVideoRenderer.videoId;
                ti1 = '[Deleted Video]';
}
    ss += '{vid:"' + ide + '",tit:"' + ti1 + '"}';
    if(i != (len - 1)){
        ss += ',\n';
    }
} 
glStr = 'obj = \n[' + ss + '\n];\n';
document.getElementById('area2').value = glStr;
document.getElementById('len').innerHTML = len + ' videos';
}
function test(){
var head = document.getElementsByTagName('head').item(0);
var script = document.createElement('script');
script.setAttribute('type', 'text/javascript');
script.innerHTML = glStr;
head.appendChild(script);
 alert('obj.length = ' + obj.length);
 alert('obj[5].vid = ' + obj[5].vid + '\n obj[5].tit = ' +   obj[5].tit);
}
</script>
</body>
于 2020-04-22T08:28:50.260 回答
0

我做了如下,但我不知道这个是优化的,还是不知道我是如何得到我预期的结果的。

说明: 将从播放列表中检索所有视频并动态推送到数组中。

服务中:

    getSnippets(token): any {
    console.log('API_TOKEN:',token);
    if(token){
      return this.http.get('https://www.googleapis.com/youtube/v3/playlistItems?part=snippet&playlistId=PLV_aspERmuCKxUPxu8UwUd3I52VLje0ra&maxResults=100&key=[API_KEY]='+token).toPromise();
    }else{
      return this.http.get('https://www.googleapis.com/youtube/v3/playlistItems?part=snippet&playlistId=PLV_aspERmuCKxUPxu8UwUd3I52VLje0ra&maxResults=100&key=[API_KEY]').toPromise();
    }
  }

要显示数据:

      async getPlayList(){
    try{
      let pageToken;
      this.finalAr = [];
      // for(let t = 0; t <= 1; t++) {
        const list = await this.service.getSnippets(pageToken);
        pageToken          = list.nextPageToken;
        // let pageInfo       = list.pageInfo;
        let pageTot        = list.pageInfo.totalResults;
        let resultsPerPage = list.pageInfo.resultsPerPage;
        let loopCnt        = pageTot / resultsPerPage;
        let finalCnt       = Math.abs(Math.ceil(loopCnt)) - 1 ;
        if(pageToken != undefined || pageToken != null){
          let tempAr   = list.items;        
          for(let i = 0; i < tempAr.length; i++){
            this.finalAr.push({"vid_id"   : tempAr[i].snippet.resourceId.videoId,
                               "vid_title": tempAr[i].snippet.title,
                               "vid_desc" : tempAr[i].snippet.description,
                               "vid_icon" : 'https://i.ytimg.com/vi/'+tempAr[i].snippet.resourceId.videoId+'/sddefault.jpg'
                              })
          }
          console.log('finalAr_1:',this.finalAr);
        }
        for(let a = 1; a <= finalCnt; a++){
          const listF = await this.service.getSnippets(pageToken);
            pageToken = listF.nextPageToken;
            let tempAr   = listF.items;      
            for(let i = 0; i < tempAr.length; i++){
              this.finalAr.push({"vid_id"   : tempAr[i].snippet.resourceId.videoId,
                                 "vid_title": tempAr[i].snippet.title,
                                 "vid_desc" : tempAr[i].snippet.description,
                                 "vid_icon" : 'https://i.ytimg.com/vi/'+tempAr[i].snippet.resourceId.videoId+'/sddefault.jpg'
                                })
            }
            console.log('finalAr_2:',this.finalAr);
        }
    }catch (e){
      console.log('ER:',e);
    }

做了工作。但是,如果有人知道这件事,我想从多个播放列表中检索所有视频,请告诉我。

于 2020-09-30T08:51:06.600 回答