使用 Java 获取 YouTube 播放列表的所有视频

Posted

技术标签:

【中文标题】使用 Java 获取 YouTube 播放列表的所有视频【英文标题】:Get all videos of a YouTube Playlist in Java 【发布时间】:2016-11-19 00:30:09 【问题描述】:

上下文我正在使用 android Studio (Java)。我想获取给定播放列表的所有视频(或 50 个,之后我将获取所有其他视频)。

问题我看到人们使用 url 之类的 https://www.googleapis.com/youtube/v3/playlistItems?part=snippet&maxResults=50&playlistId=PLiEwZfNgb4fVrRzTonlVEMj6DB2Nmzg2M&key=AIzaSyC2_YRcTE9916fsmA0_KRnef43GbLzz8m0 但我不知道如何在 Java 中实现这一点。我遵循了一些教程,我得到了一种获取完全不同的信息的方法,例如:

YouTube.Search.List query;
query = youtube.search().list("id,snippet");
      query.setKey(MY_API_KEY);
      query.setMaxResults((long)20);
      query.setType("video");
      query.setFields("items(id/videoId,snippet/title,snippet/description,snippet/thumbnails/default/url)");

而且我真的不明白除了搜索之外我如何获得其他东西。 大多数文档都是英文的...

编辑 好的,所以我继续尝试,我想我得到了一个接近的解决方案,但是我得到了一个错误。

private YouTube youtube;
private YouTube.PlaylistItems.List playlistItemRequest;
private String PLAYLIST_ID = "PLiEwZfNgb4fVrRzTonlVEMj6DB2Nmzg2M";
public static final String KEY = "AIzaSyC2_YRcTE9916fsmA0_KRnef43GbLzz8m0";

// Constructor
public YoutubeConnector(Context context)

    youtube = new YouTube.Builder(new NetHttpTransport(),
            new JacksonFactory(), new HttpRequestInitializer()
    
        @Override
        public void initialize(HttpRequest hr) throws IOException 
    ).setApplicationName(context.getString(R.string.app_name)).build();


public List<VideoItem> result()

    List<PlaylistItem> playlistItemList = new ArrayList<PlaylistItem>();
    try
    
    /* HERE MUST BE MY PROBLEM ! */
        playlistItemRequest = youtube.playlistItems().list("snippet");
        playlistItemRequest.setPlaylistId(PLAYLIST_ID);
        playlistItemRequest.setFields("items(id/videoId,snippet/title,snippet/description,snippet/thumbnails/default/url),nextPageToken,pageInfo");
        playlistItemRequest.setKey(KEY);
        String nextToken = "";
        do 
            playlistItemRequest.setPageToken(nextToken);
            PlaylistItemListResponse playlistItemResult = playlistItemRequest.execute();

            playlistItemList.addAll(playlistItemResult.getItems());

            nextToken = playlistItemResult.getNextPageToken();
         while (nextToken != null);
    catch(IOException e)
    
        Log.d("YC", "Could not initialize: "+e);
    
//[...]

这是我得到的错误: "code" : 400, "errors" : [ "domain" : "global", "location" : "fields", "locationType" : "parameter", "message" : "Invalid field selection videoId", "reason" : "invalidParameter" ], "message" : "Invalid field selection videoId"

编辑 2 感谢:Martijn Woudstra。 正确的行是:

playlistItemRequest = youtube.playlistItems().list("snippet,contentDetails");
//[...]
playlistItemRequest.setFields("items(snippet/title,snippet/description,snippet/thumbnails/default/url,contentDetails/videoId),nextPageToken,pageInfo");
//[...]
videoItem.setId(item.getContentDetails().getVideoId());

【问题讨论】:

我为你的问题添加了一个答案~希望你觉得它有用 【参考方案1】:

id/videoId 不存在。 有一个id 和一个snippet/resourceId/videoId。 所以我的猜测是你的 setfields 不正确。

【讨论】:

不知道为什么网站和代码中的层次结构不一样,但我是item/ContentDetails/VideoId。您的评论对我帮助很大,谢谢。【参考方案2】:

我知道这是一个老问题,但重要的是要确定我们使用哪些资源来了解如何获取正确的信息。 YouTube API v3 中有很多资源,但我们通常使用searchvideoplaylistplaylistItems

根据文档,以下 JSON 结构显示了 playlistItems 资源的格式:


  "kind": "youtube#playlistItem",
  "etag": etag,
  "id": string,
  "snippet": 
    "publishedAt": datetime,
    "channelId": string,
    "title": string,
    "description": string,
    "thumbnails": 
      (key): 
        "url": string,
        "width": unsigned integer,
        "height": unsigned integer
      
    ,
    "channelTitle": string,
    "playlistId": string,
    "position": unsigned integer,
    "resourceId": 
      "kind": string,
      "videoId": string,
    
  ,
  "contentDetails": 
    "videoId": string,
    "startAt": string,
    "endAt": string,
    "note": string,
    "videoPublishedAt": datetime
  ,
  "status": 
    "privacyStatus": string
  

从这个结构中,我们可以假设有三种方法可以得到videoId。但首先重要的是要知道我们将如何定义资源的 PARTSFIELDS

要定义 PARTS,我们使用以下代码:

YouTube.PlaylistItems.List list = youtube.playlistItems().list("snippet");

在上一行中,"snippet" 标识了一个包含许多字段(或子属性)的属性,包括titledescriptionpositionresourceId,所以当我们设置"snippet" API 的响应将包含所有这些子属性。

现在,如果我们定义 FIELDS,我们也可以限制以前的属性。例如,在这段代码中:

list.setFields("items(id/videoId,snippet/title,snippet/description," +
    "snippet/thumbnails/default/url)");

如果我们调用list.execute(),它会显示错误,因为我们没有在PARTS 属性中定义id。此外,根据 JSON 结构,id 是一个字符串,不包含 videoId 作为子属性。啊!但是我们可以从resourceId 中提取videoId? -嗯,答案是YES/NO。 -为什么这样?来吧 Teo,JSON 结构清楚地显示了它。 -是的,我可以看到,但是文档说:

如果 snippet.resourceId.kind 属性的值为 youtube#video,则该属性将存在,​​并且其值将包含 YouTube 用于唯一标识播放列表中的视频的 ID。

这意味着有时可能不可用。 -那么,我们如何获得videoId? -好吧,我们可以将idcontentDetails 添加到PARTS 资源中。如果我们添加 id 然后定义如下字段:

YouTube.PlaylistItems.List list = youtube.playlistItems().list("id,snippet");
list.setFields("items(id,snippet/title,snippet/description," +
    "snippet/thumbnails/default/url)");

如果我们添加 contentDetails 然后定义如下字段:

YouTube.PlaylistItems.List list = youtube.playlistItems()
    .list("snippet,contentDetails");
list.setFields("items(contentDetails/videoId,snippet/title,snippet/description," +
    "snippet/thumbnails/default/url)");

希望对大家有帮助。

【讨论】:

以上是关于使用 Java 获取 YouTube 播放列表的所有视频的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 YouTube Analytics API 获取任何 Youtube 频道的订阅用户列表及其详细信息?

如何使用 javascript API 和 json 获取 youtube 播放列表

如何使用 JavaScript API V3 以 JSON 格式获取 youtube 播放列表的数据

从 youtube 频道获取视频列表

使用 JSON 从 YouTube 频道获取视频列表

如何使用 youtube api 获取按发布日期排序的播放列表的视频